forked from hznuhisejeffrey/opencv_moveTest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.cpp
255 lines (232 loc) · 5.64 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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/types_c.h>
#include <iostream>
using namespace cv;
using namespace std;
#define BACKGROUND_NUM 10
const int alphList[BACKGROUND_NUM] = {1,1,2,2,3,3,4,4,40,40};
static void creatWindow(const char *name, int x = 0, int y = 0, int width = 320, int height = 240);
static Mat creatBackGround(Mat *imageList, int num);
static void updateQueue(Mat *ImageList, Mat newImage, int len);
uchar *getHorizontal(Mat img);
uchar *getVertical(Mat img);
bool isBlack(Mat image);
static void computerRectangle(Mat &image, Point &p1, Point &p2);
int main(void)
{
VideoCapture capture(0); //打开摄像头
capture.set(CAP_PROP_FRAME_WIDTH, 320);
capture.set(CAP_PROP_FRAME_HEIGHT, 240);
creatWindow("捕捉窗口");
//读取25帧图像用于计算背景模型
Mat *backGroundList = new Mat[BACKGROUND_NUM];
for (int i = 0; i < BACKGROUND_NUM; i++)
{
Mat frame;
capture >>frame;
if(frame.empty())
return -1;
cvtColor(frame, backGroundList[i], CV_BGR2GRAY);
}
Mat backGround = creatBackGround(backGroundList, BACKGROUND_NUM);
// imshow("捕捉窗口", backGround);
while(1)
{
Mat frame;
Mat grayFrame;
Mat diff;
Point p1 = Point(20, 20);
Point p2 = Point(200, 200);
Mat element = getStructuringElement( MORPH_RECT, Size(3, 3), Point(-1, -1) );
capture >>frame;
if(frame.empty())
return -1;
blur(frame, frame, Size(3, 3), Point(-1, -1)); //均值滤波
cvtColor(frame, grayFrame, CV_BGR2GRAY); //转换成灰度图像
diff = grayFrame - backGround;
threshold(diff, diff, 10, 255, THRESH_BINARY); //对差值图像进行二值化
blur(diff, diff, Size(3, 3), Point(0, 0));
dilate(diff, diff, element);
computerRectangle(diff, p1, p2); //计算检测矩形
rectangle( frame, p1, p2, Scalar(0,0,255), 3, 1 ,0 ); //将矩形添加进图像中
updateQueue(backGroundList, grayFrame, BACKGROUND_NUM);
backGround = creatBackGround(backGroundList, BACKGROUND_NUM);
imshow("捕捉窗口", frame);
imshow("差值窗口", diff);
waitKey(1);
}
delete []backGroundList;
return 0;
}
/*
* 函数名称:
* 函数功能:
* 输入参数:
* 输出参数:
*/
static void creatWindow(const char *name, int x, int y, int width, int height)
{
namedWindow(name, 0);
moveWindow(name, x, y);
resizeWindow(name, width, height);
}
/*
* 函数名称:
* 函数功能:
* 输入参数:
* 输出参数:
*/
static Mat creatBackGround(Mat *imageList, int num)
{
Mat _backGround = Mat::zeros(imageList[0].size(), CV_8U);
for (int x = 0; x < imageList[0].rows; x++)
{
for (int y = 0; y < imageList[0].cols; y++)
{
int pixel_sum = 0;
for (int n = 0; n < num; n++) //计算25帧对应像素的总值
{
pixel_sum += imageList[n].at<uchar>(x, y) * alphList[n]; //乘以权重
}
_backGround.at<uchar>(x, y) = pixel_sum / 100;
}
}
return _backGround;
}
/*
* 函数名称:
* 函数功能:
* 输入参数:
* 输出参数:
*/
static void updateQueue(Mat *ImageList, Mat newImage, int len)
{
for (int i = 0; i < len - 1; i++)
{
ImageList[i] = ImageList[i+1];
}
ImageList[len-1] = newImage;
}
/*
* 函数名称:getHorizontal
* 函数功能:获取图像的水平投影
* 输入参数:需要计算水平投影的图像
* 输出参数:水平投影序列,并由一个指针指向,并返回这个指针
*/
uchar *getHorizontal(Mat img)
{
int pixel_sum ;
uchar *horizontalList = new uchar[img.rows];
for (int x = 0; x < img.rows; x++)
{
pixel_sum = 0;
for (int y = 0; y < img.cols; y++)
{
pixel_sum += img.at<uchar>(x, y); //将每列的像素值累加
}
horizontalList[x] = pixel_sum / img.cols; //取平均值
}
return horizontalList;
}
/*
* 函数名称:getVertical
* 函数功能:获取图像的垂直投影
* 输入参数:需要计算垂直投影的图像
* 输出参数:垂直投影序列,并由一个指针指向,并返回这个指针
*/
uchar *getVertical(Mat img)
{
int pixel_sum ;
uchar *verticalList = new uchar[img.cols];
for (int y = 0; y < img.cols; y++)
{
pixel_sum = 0;
for (int x = 0; x < img.rows; x++)
{
pixel_sum += img.at<uchar>(x, y); //将每行的像素值累加
}
verticalList[y] = pixel_sum / img.rows;
}
return verticalList;
}
/*
* 函数名称:
* 函数功能:
* 输入参数:
* 输出参数:
*/
bool isBlack(Mat image)
{
int sum;
for (int x = 0; x < image.rows; x++)
{
for (int y = 0; y < image.cols; y++)
{
if (image.at<uchar>(x, y) != 0)
{
sum++;
if(sum > 10)
return false;
}
}
}
return true;
}
/*
* 函数名称:
* 函数功能:
* 输入参数:
* 输出参数:
*/
static void computerRectangle(Mat &image, Point &p1, Point &p2)
{
p1 = Point(0, 0);
p2 = Point(0, 0);
if ( isBlack(image) ) //是全黑的图像?
{
p1 = Point(0, 0);
p2 = Point(0, 0);
}
uchar *x_shadowArray = getHorizontal(image); //存放水平投影序列
uchar *y_shadowArray = getVertical(image); //存放垂直投影序列
/* 寻找最左x坐标 */
for (int x = 0; x < image.cols - 1; x++)
{
if ( y_shadowArray[x+1] != 0 )
{
p1.x = x+1;
break;
}
}
/* 寻找最右x坐标 */
for (int x = image.cols - 1; x > 0; x--)
{
if ( y_shadowArray[x-1] != 0 )
{
p2.x = x-1;
break;
}
}
/* 寻找最上y坐标 */
for (int y = 0; y < image.rows - 1; y++)
{
if ( x_shadowArray[y+1] != 0 )
{
p1.y = y+1;
break;
}
}
/* 寻找最下y坐标 */
for (int y = image.rows - 1; y > 0; y--)
{
if ( x_shadowArray[y-1] != 0 )
{
p2.y = y-1;
break;
}
}
delete []x_shadowArray;
delete []y_shadowArray;
}