# 1. 基础类型与图像视频读取
## 1. 基础类型
### 1. 接口类
OpenCV是一个极其庞大的库,有不可估量的函数数目。受限于类的重载函数数目和种类,内部函数互相调用之间,通常会使用接口类去做隐式类型转换,然后再去进行统一的运算处理这些类通过调用 `InputArray` 来进行隐式转换,方便使用 ,如:
`Mat` `Mat_<T>` `Matx<T m n>` `std::vector<T>` `std::vector<std::vector<T>` `std::vector<Mat>` `std::vector<Mat_<T>>` `UMat` `std::vector<UMat>`;
> :-- 讲解接口类的概念,只是为了大家可以学习OpenCV的编写思想,从而更方便去学好这个库,1.1.1小节内容不要求会编写
| 类型 | 说明 |
| :------------------------- | :----------------------------------------------------------- |
| `InputArray` | 只读输入数组传递到 OpenCV 函数的代理类 |
| `OutputArray` | 这种类型与 `InputArray` 非常相似,只是它用于输入/输出和输出函数参数 |
| `InputOutputArray` | 继承了OutputArray,作为输入输出接口,增加了一些功能 |
| `InputArrayOfArrays` | typedef `InputArray` `InputArrayOfArrays` |
| `OutputArrayOfArrays` | typedef `OutputArray` `OutputArrayOfArrays` |
| `InputOutputArrayOfArrays` | typedef `OutputArray` `InputOutputArrayOfArrays` |
> *经验分享*
> Array 是数组的意思,更直观的理解方式是一个排列,是有线性储存方式的数据的集合。
> Input 和 Output 在解读代码时是为了标注输入输出使用,如果查看源码[^source],可发现InputArray是首先编写的基本接口,而OutputArray是对InputArray的继承,增加了一些作为输出类所应有的成员;在此之上,又有InputOutputArray继承了OutputArray,作为输入输出接口,它的功能比前两者更多,也能起到更多的作用。
> 因此我们可以理解了`输入排列:InputArray` `输出排列:OutputArray` `输入输出排列:InputOutputArray`三个类。
> 之后三者是ArraysOfArrays,是前三者的排列,即排列的排列,定义使用了typedef。
#### 2. Mat 图像类
`Mat`本质是一个n维密集运算数组,是Matrix的简写。相似的有`UMat`,表示GPU Mat,`GMat`,表示G-API的Mat接口。
#### 3. 运算类
OpenCV的运算内核原型类,详情见 `<opencv2/core/matx.hpp>`
| 类型 | 说明 |
| ------ | ------ |
| `Matx` | 定阶矩阵类,即确定规模大小的矩阵类 |
| `Vec` | 向量类 |
#### 4. 定义类
这是OpenCV官方定义的一些常用的类型,详情见`<opencv2/core/types.hpp>`
| 类型 | 说明 |
| ------------- | ---------- |
| `Point` | 二维点类 |
| `Point3` | 三维点类 |
| `Rect` | 矩形类 |
| `RotatedRect` | 旋转矩形类 |
| `Range` | 范围类 |
| `Scalar` | 通道类 |
| `Size` | 规格类 |
## 2. 图像视频IO
1. 函数
1. imread
```C++
Mat cv::imread ( const String & filename,
int flags = IMREAD_COLOR
)
/*
@brief Loads an image from a file.
简介 从文件加载图像。
The function imread loads an image from the specified file and returns it. If the image cannot be read (because of missing file, improper permissions, unsupported or invalid format), the function returns an empty matrix ( Mat::data==NULL ).
函数imread从指定文件加载图像并返回。如果无法读取图像(由于缺少文件、权限不正确、格式不受支持或无效),函数将返回一个空矩阵(Mat::data==NULL)。
@param filename Name of file to be loaded.
@param flags Flag that can take values of cv::ImreadModes
*/
```
2. imwrite
```C++
bool cv::imwrite ( const String & filename,
InputArray img,
const std::vector<int>> & params = std::vector< int >()
)
/*
@brief Saves an image to a specified file.
简介 将图像保存到指定文件。
The function imwrite saves the image to the specified file. The image format is chosen based on the filename extension (see cv::imread for the list of extensions). In general, only 8-bit single-channel or 3-channel (with 'BGR' channel order) images can be saved using this function
imwrite函数将图像保存到指定的文件中。根据文件扩展名选择图像格式(有关扩展名列表,请参阅cv::imread)。通常,使用此功能只能保存8位单通道或3通道(具有“BGR”通道顺序)图像
@param filename Name of the file.
@param img (Mat or vector of Mat) Image or Images to be saved.
@param params Format-specific parameters encoded as pairs (paramId_1, paramValue_1, paramId_2, paramValue_2, ... .) see cv::ImwriteFlags
*/
```
2. 类
1. `VideoCapture`
```C++
// 常用函数
VideoCapture (const String &filename, int apiPreference=CAP_ANY)
VideoCapture (int index, int apiPreference=CAP_ANY)
virtual bool open (const String &filename, int apiPreference=CAP_ANY)
virtual bool open (int index, int apiPreference=CAP_ANY)
virtual bool isOpened () const
virtual double get (int propId) const
virtual bool set (int propId, double value)
virtual void read ()
virtual void release ()
virtual VideoCapture & operator>> (const Mat &image)
```
```C++
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
int main(int, char**)
{
Mat frame;
//--- INITIALIZE VIDEOCAPTURE
VideoCapture cap;
// open the default camera using default API
// cap.open(0);
// OR advance usage: select any API backend
int deviceID = 0; // 0 = open default camera
int apiID = cv::CAP_ANY; // 0 = autodetect default API
// open selected camera using selected API
cap.open(deviceID, apiID);
// check if we succeeded
if (!cap.isOpened()) {
cerr << "ERROR! Unable to open camera\n";
return -1;
}
//--- GRAB AND WRITE LOOP
cout << "Start grabbing" << endl
<< "Press any key to terminate" << endl;
for (;;)
{
// wait for a new frame from camera and store it into 'frame'
cap.read(frame);
// check if we succeeded
if (frame.empty()) {
cerr << "ERROR! blank frame grabbed\n";
break;
}
// show live and wait for a key with timeout long enough to show images
imshow("Live", frame);
if (waitKey(5) >= 0)
break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}
```
2. `VideoWriter`
```C++
//常用函数
VideoWriter (const String &filename, int apiPreference, int fourcc, double fps, Size frameSize, bool isColor=true)
//VideoWriter进行了四次有参重载,一次无参重载
virtual bool isOpened () const
virtual bool open (const String &filename, int fourcc, double fps, Size frameSize, bool isColor=true)
//open进行了四次重载
virtual double get (int propId) const
virtual bool set (int propId, double value)
virtual VideoWriter & operator<< (const Mat &image)
```
```C++
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
int main(int, char**)
{
Mat src;
// use default camera as video source
VideoCapture cap(0);
// check if we succeeded
if (!cap.isOpened()) {
cerr << "ERROR! Unable to open camera\n";
return -1;
}
// get one frame from camera to know frame size and type
cap >src;
// check if we succeeded
if (src.empty()) {
cerr << "ERROR! blank frame grabbed\n";
return -1;
}
bool isColor = (src.type() == CV_8UC3);
//--- INITIALIZE VIDEOWRITER
VideoWriter writer;
int codec = VideoWriter::fourcc('M', 'J', 'P', 'G'); // select desired codec (must be available at runtime)
double fps = 25.0; // framerate of the created video stream
string filename = "./live.avi"; // name of the output video file
writer.open(filename, codec, fps, src.size(), isColor);
// check if we succeeded
if (!writer.isOpened()) {
cerr << "Could not open the output video file for write\n";
return -1;
}
//--- GRAB AND WRITE LOOP
cout << "Writing videofile: " << filename << endl
<< "Press any key to terminate" << endl;
for (;;)
{
// check if we succeeded
if (!cap.read(src)) {
cerr << "ERROR! blank frame grabbed\n";
break;
}
// encode the frame into the videofile stream
writer.write(src);
// show live and wait for a key with timeout long enough to show images
imshow("Live", src);
if (waitKey(5) >= 0)
break;
}
// the videofile will be closed and released automatically in VideoWriter destructor
return 0;
}
```
[^source]: *见 [`<opencv2/core/mat.hpp>`*](https://gitee.com/c12h22o11/opencv/blob/4.x/modules/core/include/opencv2/core/mat.hpp) : Start with Line 73