这是Eva今年暑假学的~
Chapter 1 视频读写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <opencv2/opencv.hpp> #include <iostream>
using namespace std; using namespace cv;
int main(){ VideoCapture capture; capture.open("D:/.../"); if(!capture.isOpened()){ cout << "could not load" << endl; return -1; } double fps = capture.get(CV_CAP_PROP_FPS); VedioWriter writer("...", -1, fps, Size(640, 480), true); Mat frame, gray, binary; namedWindow("Video-demo", CV_WINDOW_AUTOSIZE); while(capture.read(frame)){ bitwise_not(frame, frame); imshow("Video-demo", frame); char c = waitKey(100); if(c == 27){ break; } } waitKey(0); return 0; }
|
相关类和函数
Capture 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| VideoCapture::VideoCapture(); VideoCapture::VideoCapture(const string& filename); VideoCapture::VideoCapture(int device);
bool VideoCapture::open(const string& filename); bool VideoCapture::open(int device);
VideoCapture capture; capture.open("dog.avi");
VideoCapture("dog.avi");
bool VideoCapture::isOpened();
void VideoCapture::release();
bool VideoCapture::grab();
bool VideoCapture::retrieve(Mat& image, int channel=0);
VideoCapture& VideoCapture::operator>>(Mat& image); bool VideoCapture::read(Mat& image);
capture.read(frame);
capture.grab();
capture.retrieve(frame);
capture >> frame;
double VideoCapture::get(int propId);
bool VideoCapture::set(int propertyId, double value);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> int main(int argc,char* argv[]) { cv::VideoCapture capture(argv[1]); if(!capture.isOpened()) { std::cout<<"video not open."<<std::endl; return 1; } double rate = capture.get(CV_CAP_PROP_FPS); cv::Mat frame; int delay = 1000/rate; bool stop(false); while(!stop) { if(!capture.read(frame)) { std::cout<<"no video frame"<<std::endl; break; } int frame_num = capture.get(CV_CAP_PROP_POS_FRAMES); std::cout<<"Frame Num : "<<frame_num<<std::endl; if(frame_num==20) { capture.set(CV_CAP_PROP_POS_FRAMES,10); } cv::imshow("video",frame); if(cv::waitKey(delay)>0) stop = true; } capture.release(); return 0; }
|
VideoWriter 类
1 2 3 4 5 6
| VideoWriter::VideoWriter()
VideoWriter::VideoWriter(const String &filename, int fourcc, double fps, Size frameSize, bool isColor=true)
VideoWriter::VideoWriter(const String &filename, int apiPreference, int fourcc, double fps, Size frameSize, bool isColor=true)
|
filename : 输出视频文件的路径名称
fourcc : 字符类型的编码,表示用于编码视频文件的编码器。其中
VideoWriter::fourcc('P’,’I’,’M’,’1’)
表示 MPEG-1
编码文件扩展名为 .avi
;
VideoWriter::fourcc('X','V','I','D')
表示 MPEG-4
编码文件扩展名为 .avi
;
VideoWriter::fourcc('X',’2','6','4')
表示 MPEG-4
编码文件扩展名为 .mp4
;
VideoWriter::fourcc('I',’4','2','0')
表示 YUV
编码,文件扩展名为.avi
;
VideoWriter::fourcc('M',’P','4','V')
表示旧的 MPEG-4
编码,文件扩展名为 .avi
;
VideoWriter::fourcc('T',’H','E','O')
表示使用 ogg vorbis
,文件扩展名为 .ogv
;
VideoWriter::fourcc('F','L','V','1')
表示 flash video
,文件扩展名为 .flv
;
fps : 表示帧率
frameSize : 表示每一帧图像的大小
isColor : 灰度图像或者是彩色图像(仅仅在 windows 上支持)
apiPreference : 使用指定的 API,例如可以使用 cv::CAP_FFMPEG 或者 cv::CAP_GSTREAMER 等。
1 2 3 4 5 6 7 8 9 10 11 12
| VideoWriter::isOpened() VideoWriter::getBackednName() VideoWriter::open(const String &filename, int fourcc, double fps, Size frameSize, bool isColor=true);VideoWriter::open(const String &filename,int apiPreference,int fourcc,double fps,Size frameSize,bool isColor=true);
VideoWriter::release() VideoWriter::get(int propId);
VideoWriter::set(int propId,double value);
|
Size 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| template<typename _Tp> class Size_ { public: typedef _Tp value_type; Size_(); Size_(_Tp _width, _Tp _height); Size_(const Size_& sz); Size_(const CvSize& sz); Size_(const CvSize2D32f& sz); Size_(const Point_<_Tp>& pt); Size_& operator = (const Size_& sz); _Tp area() const; template<typename _Tp2> operator Size_<_Tp2>() const; operator CvSize() const; operator CvSize2D32f() const; _Tp width, height; };
|
cvtColor
_CV_8U_ 图像 其通道值范围为0到255
_CV_16U_ 时其值通道值范围为0到65535
_CV_32F_ 时,其通道值范围为0到1
1 2
| void cv::cvtColor (InputArray src, OutputArray dst, int code, int dstCn = 0)
|
threshold
去掉噪,例如过滤很小或很大像素值的图像点
1 2 3 4 5 6
| double threshold( InputArray src, OutputArray dst, double thresh, double maxval, int type )
|
二值化的方式, 常用的有如下5种
1 2 3 4 5
| CV_THRESH_BINARY =0, CV_THRESH_BINARY_INV =1, CV_THRESH_TRUNC =2, CV_THRESH_TOZERO =3, CV_THRESH_TOZERO_INV =4,
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include<opencv2/opencv.hpp> using namespace cv; int main() { Mat src = imread("C:/Users/Administrator/Desktop/txyzm.png"); if (src.empty()) { return -1; } Mat graySrc,dst; cvtColor(src, graySrc,CV_BGR2GRAY); threshold(graySrc, dst, 170, 255, CV_THRESH_BINARY); imshow("dst", dst); waitKey(0); return 0; }
|
bitwise
1 2 3 4
| bitwise_not(InputArray src, OutputArray dst, InputArray mask = noArray());
|
namedWindow
1
| void nameWindow(const string& winname,int flags = WINDOW_AUTOSIZE) ;
|
Qt后端支持标志:
WINDOW_NORMAL
或 WINDOW_AUTOSIZE
WINDOW_NORMAL
使您可以调整大小窗口,而 WINDOW_AUTOSIZE
自动调整窗口大小以适应显示图像(参见 imshow
),您无法手动更改窗口大小。
WINDOW_FREERATIO
或 WINDOW_KEEPRATIO
WINDOW_FREERATIO
调整图像不考虑其比例,而 WINDOW_KEEPRATIO
保持图像比例。
WINDOW_GUI_NORMAL
或 WINDOW_GUI_EXPANDED
WINDOW_GUI_NORMAL
是绘制窗口的旧方法没有状态栏和工具栏,而 WINDOW_GUI_EXPANDED
是一个新的增强 GUI
。
默认情况下,flags == WINDOW_AUTOSIZE | WINDOW_KEEPRATIO |WINDOW_GUI_EXPANDED
Chapter 2 背景消去建模(BSM):背景不常变化的
图像分割 (GMM — 高斯混合模型)
1 2 3 4 5 6 7 8 9 10 11
| Ptr<BackgroundSubtractorMOG2> bgsubtractor = createBackgroundSubtractorMOG2(); bgsubtractor->setHistory(20); bgsubtractor->setVarThreshold(100); bgsubtractor->setDetectShadows(true); bgsubtractor->setBackgroundRatio(4); bgsubtractor->setNMixtures(5); bgsubtractor->setShadowThreshold(40); bgsubtractor->setVarInit(15); bgsubtractor->setVarMax(20); bgsubtractor->setVarMin(4); bgsubtractor->setVarThresholdGen(100);
|
History:用于训练背景的帧数,history可以用于计算当前的learning rate ,history越大,learning rate越低,背景更新越缓慢;
VarThreshold:方差阈值,主要用于判断前景还是背景,值越大,灵敏度越低
DetectShadows:是否检测有影子,开启后会增加算法复杂度
NMixtures:高斯模型个数,默认5个,最多8个,模型数越多,耗时越长
BackgroundRatio:高斯背景模型权重和阈值,nmixtures个模型按权重排序后,只取模型权重累加值大于backgroundRatio的前几个作为背景模型
VarInit:新建高斯模型的方差初始值,默认15
VarMax:背景更新时,用于限制高斯模型方差的最大值,默认20
VarMin:背景更新时,用于限制高斯模型方差的最小值,默认4
VarThresholdGen:方差阈值,用于已经存在的匹配的模型,如果不存在则新建一个
原文链接:https://blog.csdn.net/holecloud/article/details/80139297
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <opencv2/opencv.hpp> #include <iostream>
using namespace std; using namespace cv;
int main(){ VideoCapture capture; capture.open("..."); if(!capture.isOpened()){ cout << "could not load" << endl; return -1; } Mat frame; Mat bsmaskMOG2; namedWindow("input video", CV_WINDOW_AUTOSIZE); namedWindow("MOG2", CV_WINDOW_AUTOSIZE); Ptr<BackgroudSubtractor> pMOG2 = createBackgroundSubtractorMOG2(); while(capture.read(frame)){ imshow("inpupt video", frame); pMOG2 -> apply(frame, bsmaskMOG2); imshow("MOG2", bsmaskMOG2); char c = waitKey(100); if(c == 27){ break; } } capture.release(); waitKey(0); return 0; }
|
机器学习(KNN — K 个最近邻)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <opencv2/opencv.hpp> #include <iostream>
using namespace std; using namespace cv;
int main(){ VideoCapture capture; capture.open("..."); if(!capture.isOpened()){ cout << "could not load" << endl; return -1; } Mat frame; Mat bsmaskKNN; namedWindow("input video", CV_WINDOW_AUTOSIZE); namedWindow("KNN", CV_WINDOW_AUTOSIZE); Ptr<BackgroudSubtractor> pKNN = createBackgroundSubtractorKNN(); while(capture.read(frame)){ imshow("inpupt video", frame); pKNN -> apply(frame, bsmaskKNN); imshow("KNN", bsmaskKNN); char c = waitKey(100); if(c == 27){ break; } } capture.release(); waitKey(0); return 0; }
|
开操作去噪声
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <opencv2/opencv.hpp> #include <iostream>
using namespace std; using namespace cv;
int main(){ VideoCapture capture; capture.open("..."); if(!capture.isOpened()){ cout << "could not load" << endl; return -1; } Mat frame; Mat bsmaskMOG2; namedWindow("input video", CV_WINDOW_AUTOSIZE); namedWindow("MOG2", CV_WINDOW_AUTOSIZE); Mat kernel = getStructuringELement(MORPH_RECT, Size(3, 3), Point(-1, -1)); Ptr<BackgroudSubtractor> pMOG2 = createBackgroundSubtractorMOG2(); while(capture.read(frame)){ imshow("inpupt video", frame); pMOG2 -> apply(frame, bsmaskMOG2); morphologyEx(bsmaskMOG2, bsmaskMOG2, MORPH_OPEN, kernel, Point(-1, -1)); imshow("MOG2", bsmaskMOG2); char c = waitKey(50); if(c == 27){ break; } } capture.release(); waitKey(0); return 0; }
|
相关类和函数
BackgroundSubtractor
1 2 3
| BackgroundSubtractor (父类) - BackgroundSubtractorMOG2 - BackgroundSubtractorKNN
|
Chapter 3 对象检测与跟踪:基于颜色
inRange过滤
利用颜色进行过滤
形态学操作提取
开操作 去噪声 膨胀
轮廓查找
外接矩形获取
位置标定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #include <opencv2/opencv.hpp> #include <iostream>
using namespace std; using namespace cv;
Rect roi; void processFrame(Mat &mask, Rect &rect);
int main(){ VideoCapture capture; capture.open("..."); if(!capture.isOpened()){ cout << "could not load" << endl; return -1; } Mat frame, mask; Mat kernel1 = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); Mat kernel2 = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1)); namedWindow("input video", CV_WINDOW_AUTOSIZE); namedWindow("track mask", CV_WINDOW_AUTOSIZE); while(capture.read(frame)){ inRange(frame, Scalar(0, 0, 127), Scalar(120, 255, 120), mask); morphologyEx(mask, mask, MORPH_OPEN, kernel1, Point(-1, -1), 1); imshow("track mask", mask); dilate(mask, mask, kernel2, Point(-1, -1), 4); imshow("dilate mask", mask); processFrame(mask, roi); rectangle(frame, roi, Scalar(0, 0, 255), 3, 8, 0); imshow("input video", frame); char c = waitKey(50); if(c == 27){ break; } } capture.release(); waitKey(0); return 0; }
void processFrame(Mat &mask, Rect &rect){ vector<vector<Point> > contours; vector<Vec4i> hireachy; findContours(mask, contours, hireachy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0)); if(contours.size() > 0){ double maxArea = 0.0; for(size_t t = 0; t < contours.size(); ++t){ double area = contourArea(contours[static_cast<int>(t)]); if(area > maxArea){ maxArea = area; rect = boundingRect(contours[static_cast<int>(t)]); } } }else{ rect.x = rect.y = rect.width = rect.height = 0; } }
|
相关类和函数
inRange()
OpenCV中的inRange()函数可实现二值化功能(这点类似threshold()函数),更关键的是可以同时针对多通道进行操作,使用起来非常方便!主要是将在两个阈值内的像素值设置为白色(255),而不在阈值区间内的像素值设置为黑色(0),该功能类似于之间所讲的双阈值化操作。
1 2 3 4 5
| void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst);
|
Checks if array elements lie between the elements of two other arrays.即检查数组元素是否在另外两个数组元素值之间。这里的数组通常也就是矩阵Mat或向量。
该函数输出的dst是一幅二值化之后的图像。
morphologyEx
形态学变化函数
(4条消息) opencv 形态学变换 morphologyEx函数_keen_zuxwang的博客-CSDN博客
findContours
检测物体轮廓
1 2 3 4 5 6 7
| findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point());
|
轮廓检索模式
1 2 3 4
| CV_RETR_EXTERNAL CV_RETR_LIST CV_RETR_CCOMP CV_RETR_TREE
|
定义轮廓的近似方法
1 2 3 4
| CV_CHAIN_APPROX_NONE CV_CHAIN_APPROX_SIMPLE CV_CHAIN_APPROX_TC89_L1 CV_CHAIN_APPROX_TC89_KCOS
|
contourArea
计算轮廓面积
1 2 3
| double contourArea(InputArray contour, bool oriented = false);
|
arcLength
计算封闭轮廓周长
1 2 3
| double arcLength(InputArray curve, bool closed);
|
boundingRect
计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的
1 2
| Rect boundingRect(InputArray points);
|