-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.cpp
165 lines (128 loc) · 5.07 KB
/
main.cpp
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <string>
#include "cv.h"
#include <math.h>
using namespace cv;
using namespace std;
int main()
{
IplImage* pFrame = NULL;//视频中截取的一帧
IplImage* pFrImg = NULL;//当前帧的灰度图
IplImage* pBkImg = NULL;//当前背景的灰度图
IplImage* pFrameTemp = NULL;
CvMat* pFrameMat = NULL;//当前灰度矩阵
CvMat* pFrMat = NULL;//当前前景图矩阵
CvMat* pBkMat = NULL;//当前背景图矩阵
//形态学处理时内核大小
IplConvKernel* Element = cvCreateStructuringElementEx(13,13, 1, 1, CV_SHAPE_RECT, NULL);
//轮廓边缘提取时的参数
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contour = 0;//可动态增长元素序列
int mode = CV_RETR_EXTERNAL;//只检索最外面的轮廓
//在视频中画出感兴趣的区域
CvPoint pt1, pt2, pt3, pt4, pt5;//pt3,pt4为轮廓矩阵的左下右上
pt1.x = 400;//视频左下点
pt1.y = 0;
pt2.x = 0;//视频右上点
pt2.y = 400;
//用cvBoundingRect画出外接矩形时需要的矩形
CvRect bndRect = cvRect(0, 0, 0, 0);
//运动对象中心坐标
int avgX = 0;
int avgY = 0;
//视频捕获
CvCapture* pCapture = NULL;
//图像的帧数
int nFramNum = 0;
//创建窗口
cvNamedWindow("video", 1);
cvNamedWindow("foreground", 1);
cvMoveWindow("video", 30, 0);
cvMoveWindow("foreground", 690, 0);
pCapture = cvCaptureFromFile("video1.avi");
//pFrame = cvQueryFrame(pCapture);
pFrameTemp = cvQueryFrame(pCapture);
pFrame = cvCreateImage(cvGetSize(pFrameTemp), 8, 3);//大小和pFrameTemp相同,8Bit深度3通道图像
cvCopy(pFrameTemp, pFrame);//将所生成的临时帧复制到pFrame
//逐帧读取视频,cvQueryFrame从摄像头或者文件中抓取并返回一帧
while (pFrameTemp = cvQueryFrame(pCapture)){
cvCopy(pFrameTemp, pFrame);
nFramNum++;
//如果是第一帧,申请内存并初始化
if (nFramNum == 1){
pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U, 1);//8Bit深度,单通道图像
pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U, 1);
pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);//CV_32FC1 代表32位浮点型单通道矩阵
pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);//转换成单通道灰度图
cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
cvConvert(pFrImg, pFrameMat);//转换成矩阵
cvConvert(pFrImg, pFrMat);
cvConvert(pFrImg, pBkMat);
}
else if (nFramNum >= 2){
cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
cvConvert(pFrImg, pFrameMat);
//先高斯滤波平滑图像
cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0);
//在视频中设置并画ROI区域
cvRectangle(pFrame, pt1, pt2, CV_RGB(255, 0, 0), 2, 8, 0);//线条亮度(255,0,0)为白色,粗细2,类型8
//当前帧跟背景图相减,计算两个数组差的绝对值
cvAbsDiff(pFrameMat, pBkMat, pFrMat);
//二值化前景图
cvThreshold(pFrMat, pFrImg, 40, 255.0, CV_THRESH_BINARY);//阈值函数,类型为CV_THRESH_BINARY 二值化
//膨胀操作,内核为Element
cvDilate(pFrImg, pBkImg, Element, 1);
//通过查找边界找出ROI矩形区域内的运动车辆
cvFindContours(pBkImg, storage, &contour, sizeof(CvContour), mode, CV_CHAIN_APPROX_SIMPLE);//二值图像中寻找轮廓
//处理当前框架中移动的轮廓,用函数cvBoundingRect
for (; contour != 0; contour = contour->h_next){
//获得运动车辆的矩形
bndRect = cvBoundingRect(contour, 0);
//获得运动轮廓的平均x坐标
avgX = bndRect.x + (bndRect.width) / 2;
avgY = bndRect.y + (bndRect.height) / 2;
//如果轮廓中心点在ROI内,显示
if (avgX > 0 && avgX < 400 && avgY<400 && avgY>0){
pt3.x = bndRect.x;
pt3.y = bndRect.y;
pt4.x = bndRect.x + bndRect.width;
pt4.y = bndRect.y + bndRect.height;
//去除较小的干扰矩阵
if (bndRect.height>35 && 600<(bndRect.width*bndRect.height)<10000)
{
cvRectangle(pFrame, pt3, pt4, CV_RGB(255, 0, 0), 1, 8, 0);
}
}
}//查找边界for结束
//更新背景//////////////////////
//输入图像或序列-用于累加的图像或序列-移动平均时第一个空image所占的权重-操作符掩码
cvRunningAvg(pFrameMat, pBkMat,0.06, 0);//将pFrameMat累加到pBkMat
//将背景转换成图像格式,用以显示
cvConvert(pBkMat, pBkImg);
//显示图像///////////////////////
cvShowImage("video", pFrame);
cvShowImage("foreground", pFrImg);
cvShowImage("background", pBkImg);
//如果有按键操作,则等待
if (cvWaitKey(2) >= 0)
break;
}
waitKey(50);
}//while循环结束
//删除结构元素
cvReleaseStructuringElement(&Element);
//销毁窗口
cvReleaseMat(&pBkMat);
cvDestroyWindow("video");
cvDestroyWindow("background");
cvDestroyWindow("foreground");
//释放图像和矩阵
cvReleaseImage(&pFrImg);
cvReleaseImage(&pBkImg);
cvReleaseMat(&pFrameMat);
cvReleaseMat(&pFrMat);
}