1. Mat数据类型
1.1 Mat介绍
Mat类的声明在头文件opencv2\core\core.hpp中。
构造Mat对象,需要四个基本元素:行数,列数,通道数及其数据类型,Mat类的构造函数如下:
Mat(int rows, int cols, int type)
- rows代表行数,即图像的高度
- cols代表列数,即图像的宽度
- type代表类型,包括通道数及其数据类型
- CV_8UC(n): 8U=1字节的uchar类型
- CV_32SC(n): 32S=4字节的Short类型
- CV_32FC(n): 32F=4字节的float类型
- C(n)代表通道数
1.2 打印Mat数据
使用OpenCV提供的format()函数:
static inline
Ptr<Formatted> format(InputArray mtx, int fmt)
其中mtx为Mat数据,fmt为所支持的打印风格,其参数如下:
- Formatter::FMT_C:C风格打印(常用)
- Formatter::FMT_NUMPY: numpy风格打印
- Formatter::FMT_CSV: 逗号打印
- Formatter::FMT_PYTHON:python打印
#include <stdio.h>
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main()
{
Mat M(2, 2, CV_32FC1, Scalar(0.3));
Mat out;
M.convertTo(out, CV_8U, 255);
cout << "L= (C)" << endl << format(out, Formatter::FMT_C) << endl << endl;
cout << "L= (numpy)" << endl << format(M, Formatter::FMT_NUMPY) << endl << endl;
cout << "L= (CSV)" << endl << format(M, Formatter::FMT_CSV) << endl << endl;
cout << "L= (,)" << endl << format(M, Formatter::FMT_CSV) << endl << endl;
cout << "L= (python)" << endl << format(M, Formatter::FMT_PYTHON) << endl << endl;
return 0;
}
1.3 CV_32F转CV_8U
对于图像分割任务,输出常常是一个范围为【0,1】的浮点数类型的Mask,为了保存输出结果且避免错误,需要将去数据类型转换为CV_8U,此时可以通过opencv提供的函数convertTo完成数据类型的转换。
void cv::Mat::convertTo (OutputArray m,
int rtype,
double alpha = 1,
double beta = 0
)
// converts an array to another data type with optional scaling and shift.
- rtype:为需要转换的数据类型
- alpha:为需要对元素进行的缩放值
- beta:为平移值
Mat A; // CV_32F and range [0, 1]
Mat B;
A.convertTo(B, CV_8U, 255);
2. 图像读写
2.1. 读取图像
函数的语法格式:
retval = cv2.imread(filename, [flags])
- flags为读取标记,用于控制读取文件的类型。
- IMREAD_GRAYSCALE:该模式下读取得到的图像为单通道灰度图像,得到data的维度为【height,width】
- IMREAD_COLOR:(default)彩色图像模式,得到data的维度为【height,width,channel】
2.2. 显示图像
函数语法格式:
None = cv2.namedWindow(winname) cv2.imshow(winname, Mat)
在实际使用中,可以先通过函数namedWindow创建一个窗口,再通过imshow引用该窗口来显示图像
也可以不创建窗口,直接使用imshow引用一个并不存在的窗口,显示指定图像。
2.3. 保存图像
函数语法格式:
retval = cv2.imread(filename, mat, [params])
- params是保存类型参数,可选。
3. 视频读写
OpenCV提供cv2.VideoCapture类和cv2.VideoWriter类来支持各种类型的视频文件。
在不同操作系统中,它们支持的文件类型有所不同,但是各种操作系统中均支持AVI格式的视频文件。
3.1 VideoCapture类
1. 初始化
cv2.VideoCapture()用于打开摄像头并完成摄像头的初始化工作。
捕获对象 = cv2.VideoCapture("摄像头ID号")
- "摄像头ID号":摄像头的ID号码
- 捕获对象:返回值为VideoCapture类的对象
2. open()函数和isOpened()函数
用来检测是否初始化成功
retval = cv2.VideoCapture().isOpened()
- retval = True,表示成功
- retval = False,表示失败
3. 捕获帧数据
摄像头初始化成功后,就可以从摄像头中捕获帧信息。
retval, frame = cv2.VideoCapture.read()
- image:返回捕获得到的帧数据
- retval:捕获成功为True,失败为False
4. 释放
在不需要摄像头时,关闭摄像头。
None = cv2.VideoCapture.release()
5. 属性设置
用于获取或更改VideoCapture类对象的属性。
retval = cv2.VideoCapture.get(propid) cv2.VideoCapture.set(propid, value)
- propid:表示类对象的属性
- cv2.CAP_PROP_FRAME_WIDTH
- cv2.CAP_PROP_FRAME_HEIGHT
- cv2.CAP_PROP_FPS:帧率
- cv2.CAP_PROP_FRAME_COUNT:总帧数
- cv2.CAP_PROP_POS_MSEC:视频当前位置
3.2 VideoWriter
VideoWriter类可以将图片序列化保存成视频文件,也可以修改视频的各种属性,还可以完成对视频类型的转换。
1. 构造函数
cv2.VideoWriter(filename, fourcc, fps, frameSize, [isColor])
- fourcc表示视频编解码类型。通过VideoWriter_fourcc()来指定视频编码格式
- "I420":表示未压缩的YUV颜色编码格式,色度子采样为4:2:0.该编码格式具有较好的兼容性,但产生的文件较大,文件扩展名为".avi"
- "xvid"::表示MPEG-4编码类型。视频大小约占平均大小,生成文件的扩展名为".avi"
- "THEO":表示Ogg Vorbis编码类型,文件扩展名为".ogv"
- "FLVI":表示Flash视频,生成为文件扩展名为".flv"
2. write函数
cv2.VideoWriter.write(image)
3. 释放对象
cv2.VideoWriter.release()
3.3 python和C++的实现例子
- python实现
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
fps = cap.get(cv2.CAP_PROP_FPS)
frame_size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
out = cv2.VideoWriter('test.avi',fourcc, fps, frame_size,True)
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
cv2.imshow('frame',frame)
out.write(frame)
if cv2.waitKey(10) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
- 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;
}