开源motion代码分析
2 E币
成为会员,免费下载资料
文件大小:415.75 KB
上传者:9crk
时间:2015-02-01 23:52:31
下载量:98
本帖最后由 9crk 于 2015-2-3 13:21 编辑
motion:国外的开源视频移动侦测软件,集成了ffmpeg和流媒体服务,提供运动报警(执行脚本)及录像功能(不过不支持H264)。
借花献佛,主要分析一下其运动侦测算法。
项目主页:[url]http://sourceforge.net/projects/motion/[/url]
源码已上传:
[attach]2241[/attach]
motion接口在motion.c文件中
static void *motion_loop(void *arg)
主要关注/***** MOTION LOOP - MOTION DETECTION SECTION *****/ 这一段代码。
[code]
/* The actual motion detection takes place in the following
* diffs is the number of pixels detected as changed
* Make a differences picture in image_out
*
1.做帧差
* alg_diff_standard is the slower full feature motion detection algorithm
* alg_diff first calls a fast detection algorithm which only looks at a
* fraction of the pixels. If this detects possible motion alg_diff_standard
* is called.
*/
if (cnt->threshold && !cnt->pause) {
/* if we've already detected motion and we want to see if there's
* still motion, don't bother trying the fast one first. IF there's
* motion, the alg_diff will trigger alg_diff_standard
* anyway
*/
if (cnt->detecting_motion || cnt->conf.setup_mode)
cnt->current_image->diffs = alg_diff_standard(cnt, cnt->imgs.image_virgin);
else
cnt->current_image->diffs = alg_diff(cnt, cnt->imgs.image_virgin);
2.开关灯处理
/* Lightswitch feature - has light intensity changed?
* This can happen due to change of light conditions or due to a sudden change of the camera
* sensitivity. If alg_lightswitch detects lightswitch we suspend motion detection the next
* 5 frames to allow the camera to settle.
* Don't check if we have lost connection, we detect "Lost signal" frame as lightswitch
*/
if (cnt->conf.lightswitch && !cnt->lost_connection) {
if (alg_lightswitch(cnt, cnt->current_image->diffs)) {
if (cnt->conf.setup_mode)
motion_log(-1, 0, "Lightswitch detected");
if (cnt->moved < 5)
cnt->moved = 5;
cnt->current_image->diffs = 0;
alg_update_reference_frame(cnt, RESET_REF_FRAME);
}
}
3.开关灯滤波
/* Switchfilter feature tries to detect a change in the video signal
* from one camera to the next. This is normally used in the Round
* Robin feature. The algorithm is not very safe.
* The algorithm takes a little time so we only call it when needed
* ie. when feature is enabled and diffs>threshold.
* We do not suspend motion detection like we did for lightswitch
* because with Round Robin this is controlled by roundrobin_skip.
*/
if (cnt->conf.switchfilter && cnt->current_image->diffs > cnt->threshold) {
cnt->current_image->diffs = alg_switchfilter(cnt, cnt->current_image->diffs,
cnt->current_image->image);
if (cnt->current_image->diffs <= cnt->threshold) {
cnt->current_image->diffs = 0;
if (cnt->conf.setup_mode)
motion_log(-1, 0, "Switchfilter detected");
}
}
4.噪点消除
/* Despeckle feature
* First we run (as given by the despeckle option iterations
* of erode and dilate algorithms.//主要使用了腐蚀与膨胀操作
* Finally we run the labelling feature.
* All this is done in the alg_despeckle code.
*/
cnt->current_image->total_labels = 0;
cnt->imgs.largest_label = 0;
olddiffs = 0;
if (cnt->conf.despeckle && cnt->current_image->diffs > 0) {
olddiffs = cnt->current_image->diffs;
cnt->current_image->diffs = alg_despeckle(cnt, olddiffs);
} else if (cnt->imgs.labelsize_max) {
cnt->imgs.labelsize_max = 0; /* Disable labeling if enabled */
}
} else if (!cnt->conf.setup_mode) {
cnt->current_image->diffs = 0;
}
5.智能灵敏度设置
/* Manipulate smart_mask sensitivity (only every smartmask_ratio seconds) */
if (cnt->smartmask_speed && (cnt->event_nr != cnt->prev_event)) {
if (!--smartmask_count) {
alg_tune_smartmask(cnt);
smartmask_count = smartmask_ratio;
}
}
/* cnt->moved is set by the tracking code when camera has been asked to move.
* When camera is moving we do not want motion to detect motion or we will
* get our camera chasing itself like crazy and we will get motion detected
* which is not really motion. So we pretend there is no motion by setting
* cnt->diffs = 0.
* We also pretend to have a moving camera when we start Motion and when light
* switch has been detected to allow camera to settle.
*/
if (cnt->moved) {
cnt->moved--;
cnt->current_image->diffs = 0;
}
[/code]
可见主要是执行了alg_diff函数。
做完帧差后,再加入了开关灯切换、开关灯滤波、 噪点清除、smartMask(灵敏度设置)
算法主要在alg.c
以下是alg.h的接口函数。
[code]void alg_locate_center_size(struct images *, int width, int height, struct coord *);
void alg_draw_location(struct coord *, struct images *, int width, unsigned char *, int);
int alg_diff(struct context *, unsigned char *);
int alg_diff_standard(struct context *, unsigned char *);
int alg_lightswitch(struct context *, int diffs);
int alg_switchfilter(struct context *, int, unsigned char *);
void alg_noise_tune(struct context *, unsigned char *);
void alg_threshold_tune(struct context *, int, int);
int alg_despeckle(struct context *, int);
void alg_tune_smartmask(struct context *);
void alg_update_reference_frame(struct context *, int);[/code]
[code]int alg_diff(struct context *cnt, unsigned char *new)
{
int diffs = 0;
if (alg_diff_fast(cnt, cnt->conf.max_changes / 2, new))
diffs = alg_diff_standard(cnt, new);
return diffs;
}[/code]
主要算法接口是alg_diff,alg_diff_fast是用于减少计算量的,当帧差统计信息小于一个值时,就不执行alg_diff_standard。
分析其实现代码可以发现:噪点消除、智能灵敏度算法的主要核心还是腐蚀与膨胀操作。
motion:国外的开源视频移动侦测软件,集成了ffmpeg和流媒体服务,提供运动报警(执行脚本)及录像功能(不过不支持H264)。
借花献佛,主要分析一下其运动侦测算法。
项目主页:[url]http://sourceforge.net/projects/motion/[/url]
源码已上传:
[attach]2241[/attach]
motion接口在motion.c文件中
static void *motion_loop(void *arg)
主要关注/***** MOTION LOOP - MOTION DETECTION SECTION *****/ 这一段代码。
[code]
/* The actual motion detection takes place in the following
* diffs is the number of pixels detected as changed
* Make a differences picture in image_out
*
1.做帧差
* alg_diff_standard is the slower full feature motion detection algorithm
* alg_diff first calls a fast detection algorithm which only looks at a
* fraction of the pixels. If this detects possible motion alg_diff_standard
* is called.
*/
if (cnt->threshold && !cnt->pause) {
/* if we've already detected motion and we want to see if there's
* still motion, don't bother trying the fast one first. IF there's
* motion, the alg_diff will trigger alg_diff_standard
* anyway
*/
if (cnt->detecting_motion || cnt->conf.setup_mode)
cnt->current_image->diffs = alg_diff_standard(cnt, cnt->imgs.image_virgin);
else
cnt->current_image->diffs = alg_diff(cnt, cnt->imgs.image_virgin);
2.开关灯处理
/* Lightswitch feature - has light intensity changed?
* This can happen due to change of light conditions or due to a sudden change of the camera
* sensitivity. If alg_lightswitch detects lightswitch we suspend motion detection the next
* 5 frames to allow the camera to settle.
* Don't check if we have lost connection, we detect "Lost signal" frame as lightswitch
*/
if (cnt->conf.lightswitch && !cnt->lost_connection) {
if (alg_lightswitch(cnt, cnt->current_image->diffs)) {
if (cnt->conf.setup_mode)
motion_log(-1, 0, "Lightswitch detected");
if (cnt->moved < 5)
cnt->moved = 5;
cnt->current_image->diffs = 0;
alg_update_reference_frame(cnt, RESET_REF_FRAME);
}
}
3.开关灯滤波
/* Switchfilter feature tries to detect a change in the video signal
* from one camera to the next. This is normally used in the Round
* Robin feature. The algorithm is not very safe.
* The algorithm takes a little time so we only call it when needed
* ie. when feature is enabled and diffs>threshold.
* We do not suspend motion detection like we did for lightswitch
* because with Round Robin this is controlled by roundrobin_skip.
*/
if (cnt->conf.switchfilter && cnt->current_image->diffs > cnt->threshold) {
cnt->current_image->diffs = alg_switchfilter(cnt, cnt->current_image->diffs,
cnt->current_image->image);
if (cnt->current_image->diffs <= cnt->threshold) {
cnt->current_image->diffs = 0;
if (cnt->conf.setup_mode)
motion_log(-1, 0, "Switchfilter detected");
}
}
4.噪点消除
/* Despeckle feature
* First we run (as given by the despeckle option iterations
* of erode and dilate algorithms.//主要使用了腐蚀与膨胀操作
* Finally we run the labelling feature.
* All this is done in the alg_despeckle code.
*/
cnt->current_image->total_labels = 0;
cnt->imgs.largest_label = 0;
olddiffs = 0;
if (cnt->conf.despeckle && cnt->current_image->diffs > 0) {
olddiffs = cnt->current_image->diffs;
cnt->current_image->diffs = alg_despeckle(cnt, olddiffs);
} else if (cnt->imgs.labelsize_max) {
cnt->imgs.labelsize_max = 0; /* Disable labeling if enabled */
}
} else if (!cnt->conf.setup_mode) {
cnt->current_image->diffs = 0;
}
5.智能灵敏度设置
/* Manipulate smart_mask sensitivity (only every smartmask_ratio seconds) */
if (cnt->smartmask_speed && (cnt->event_nr != cnt->prev_event)) {
if (!--smartmask_count) {
alg_tune_smartmask(cnt);
smartmask_count = smartmask_ratio;
}
}
/* cnt->moved is set by the tracking code when camera has been asked to move.
* When camera is moving we do not want motion to detect motion or we will
* get our camera chasing itself like crazy and we will get motion detected
* which is not really motion. So we pretend there is no motion by setting
* cnt->diffs = 0.
* We also pretend to have a moving camera when we start Motion and when light
* switch has been detected to allow camera to settle.
*/
if (cnt->moved) {
cnt->moved--;
cnt->current_image->diffs = 0;
}
[/code]
可见主要是执行了alg_diff函数。
做完帧差后,再加入了开关灯切换、开关灯滤波、 噪点清除、smartMask(灵敏度设置)
算法主要在alg.c
以下是alg.h的接口函数。
[code]void alg_locate_center_size(struct images *, int width, int height, struct coord *);
void alg_draw_location(struct coord *, struct images *, int width, unsigned char *, int);
int alg_diff(struct context *, unsigned char *);
int alg_diff_standard(struct context *, unsigned char *);
int alg_lightswitch(struct context *, int diffs);
int alg_switchfilter(struct context *, int, unsigned char *);
void alg_noise_tune(struct context *, unsigned char *);
void alg_threshold_tune(struct context *, int, int);
int alg_despeckle(struct context *, int);
void alg_tune_smartmask(struct context *);
void alg_update_reference_frame(struct context *, int);[/code]
[code]int alg_diff(struct context *cnt, unsigned char *new)
{
int diffs = 0;
if (alg_diff_fast(cnt, cnt->conf.max_changes / 2, new))
diffs = alg_diff_standard(cnt, new);
return diffs;
}[/code]
主要算法接口是alg_diff,alg_diff_fast是用于减少计算量的,当帧差统计信息小于一个值时,就不执行alg_diff_standard。
分析其实现代码可以发现:噪点消除、智能灵敏度算法的主要核心还是腐蚀与膨胀操作。
展开》
折叠》