作者热门文章
- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章OpenCV实现简单摄像头视频监控程序由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
如何在冗长的监控录像中找到关键点?我们知道,监控录像中大部分信息都是没用的,那些信息就等同于一幅静态图像。我们要等待监控的范围内出现异常情况时再跟踪.
这其实是一个最简单的计算机图像处理程序。简单的思路是这样的:首先给摄像头取景采样,当背景稳定时,以该图片作为基准图片。然后在监控过程中,若出现了和基准图片反差较大的视频帧,那么启动捕捉程序,并标出异常区域.
程序如下:
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
|
#include <cv.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <highgui.h>
#define ESC 0x1b
#define TRUE 1
#define FALSE 0
// 检测图像异常,仅在采样时调用。
// 返回真表示已检测到异常,需要重新采样。
// 返回假表示未检测到异常,在一定时间后即可获取基准图像。
int
detect(CvCapture* capture, IplImage* std, IplImage* frm, CvRect* rect);
// 图像采样,确定基准图像,以便监测场景变化
// 返回真表示采样成功,返回假表示采样失败
int
gather(CvCapture* capture, IplImage* std, CvRect* rect);
// 摄像机监视,用矩形框标示出和基准图像反差较大的图像范围。
void
monitor(CvCapture* capture, IplImage* std, CvRect* rect);
// 求 x 的平方
int
square(
int
x);
int
main(
int
argc,
char
* argv[])
{
CvCapture* capture;
// 摄像机源
IplImage* std;
// 基准图像
CvRect rect;
// 异常位置矩形标识
capture = cvCreateCameraCapture(0);
if
(!capture)
return
-1;
std = cvQueryFrame(capture);
rect = cvRect(-1, -1, 0, 0);
std = cvCloneImage(std);
cvNamedWindow(
"Monitor Screen"
);
if
(gather(capture, std, &rect))
{
monitor(capture, std, &rect);
}
cvDestroyWindow(
"Monitor Screen"
);
cvReleaseImage(&std);
cvReleaseCapture(&capture);
return
0;
}
int
detect(CvCapture* capture, IplImage* std, IplImage* frm, CvRect* rect)
{
int
x, y;
// 循环变量
int
f = FALSE;
// 检测到异常的标识
int
x1 = -1, x2 = 0;
// 异常区域矩形横坐标范围
int
y1 = -1, y2 = 0;
// 异常区域矩形纵坐标范围
uchar *ptr1b, *ptr1g, *ptr1r;
// 基准图像的每个像素的三个颜色通道的值
uchar *ptr2b, *ptr2g, *ptr2r;
// 实时图像的每个像素的三个颜色通道的值
int
squaresum;
// 计算 RGB 差值平方和
// 遍历图像中的每一个点,将实时采样图与基准图做比较,检测两者的每一个
// 像素点的 RGB 差值平方和。当该值大于 8192 时(换算成灰度值则意味着
// 两者的灰度差大于 90)则立即报告出现异常,只有遍历完毕后仍未找到异
// 常才报告没有异常。
for
(y = 0; y < std->height; y++)
{
for
(x = 0; x < std->width; x++)
{
ptr1b = cvPtr2D(std, y, x) + 0; ptr2b = cvPtr2D(frm, y, x) + 0;
ptr1g = cvPtr2D(std, y, x) + 1; ptr2g = cvPtr2D(frm, y, x) + 1;
ptr1r = cvPtr2D(std, y, x) + 2; ptr2r = cvPtr2D(frm, y, x) + 2;
squaresum =
square(*ptr1b - *ptr2b) +
square(*ptr1g - *ptr2g) +
square(*ptr1r - *ptr2r);
if
(squaresum > 8192)
{
if
(f)
{
if
(x < x1) x1 = x;
else
if
(x > x2) x2 = x;
if
(y < y1) y1 = y;
else
if
(y > y2) y2 = y;
}
else
{
f = TRUE;
x1 = x; y1 = y;
x2 = x; y2 = y;
}
}
}
}
if
(x2 - x1 > frm->width / 4 || y2 - y1 > frm->height / 4)
{
f = TRUE;
}
else
{
f = FALSE;
}
*rect = cvRect(x1, y1, x2 - x1, y2 - y1);
return
f;
}
int
gather(CvCapture* capture, IplImage* std, CvRect* rect)
{
IplImage* frm;
int
except = FALSE;
// 检测到异常的标识
int
finish = FALSE;
// 采样已完成的标识
clock_t
start_time, real_time;
// 时间段监测
start_time =
clock
();
while
(!finish)
{
frm = cvQueryFrame(capture);
cvShowImage(
"Monitor Screen"
, frm);
except = detect(capture, std, frm, rect);
if
(except)
{
start_time =
clock
();
cvCopyImage(frm, std);
}
if
(cvWaitKey(15) == ESC)
break
;
real_time =
clock
();
if
(real_time - start_time >= 3000)
{
finish = TRUE;
}
}
return
finish;
}
void
monitor(CvCapture* capture, IplImage* std, CvRect* rect)
{
IplImage* frm;
int
except = FALSE;
int
finish = FALSE;
while
(!finish)
{
frm = cvQueryFrame(capture);
except = detect(capture, std, frm, rect);
if
(except)
{
cvRectangle(
frm,
cvPoint(rect->x, rect->y),
cvPoint(rect->x + rect->width, rect->y + rect->height),
cvScalar(0, 0, 255),
4);
}
cvShowImage(
"Monitor Screen"
, frm);
if
(cvWaitKey(15) == ESC)
{
finish = TRUE;
}
}
}
int
square(
int
x)
{
return
x * x;
}
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:https://blog.csdn.net/smallyang0613/article/details/38331233 。
最后此篇关于OpenCV实现简单摄像头视频监控程序的文章就讲到这里了,如果你想了解更多关于OpenCV实现简单摄像头视频监控程序的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我目前有一个工作程序正在监视一些 SQL 表并将数据传输到 MySQL 表。本质上,我有一个每 30 秒检查一次的循环。我主要担心的是,我目前每次循环时都需要关闭和打开连接。这样做的原因是因为我收到有
我是一名优秀的程序员,十分优秀!