开源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。

分析其实现代码可以发现:噪点消除、智能灵敏度算法的主要核心还是腐蚀与膨胀操作。


展开
折叠
911
评论
共 0 个
内容存在敏感词
    易百纳技术社区暂无数据
相关资料
关于作者
易百纳技术社区
9crk
贡献资料 6
易百纳技术社区 我上传的资料
登录查看
我赚取的积分
登录查看
我赚取的收益
登录查看
上传资料 赚取积分兑换E币
易百纳技术社区
删除原因
广告/SPAM
恶意灌水
违规内容
文不对题
重复发帖
置顶时间设置
结束时间
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-资料模块

审核失败

失败原因
备注
易百纳技术社区