9crk

9crk

0个粉丝

34

问答

0

专栏

6

资料

9crk  发布于  2015-02-01 23:52:53
采纳率 0%
34个问答
5541

开源motion代码分析

本帖最后由 9crk 于 2015-2-3 13:21 编辑

motion:国外的开源视频移动侦测软件,集成了ffmpeg和流媒体服务,提供运动报警(执行脚本)及录像功能(不过不支持H264)。

借花献佛,主要分析一下其运动侦测算法。

项目主页:[url]http://sourceforge.net/projects/motion/[/url]
源码已上传:
附件:motion-3.2.12.tar.gz
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-3.2.12.tar.gz
下载
我来回答
回答7个
时间排序
认可量排序

zk922

0个粉丝

4

问答

0

专栏

0

资料

zk922 2015-02-02 12:27:07
认可0
不过不支持 H264..蛋蛋的忧伤。

hanlin

0个粉丝

0

问答

0

专栏

0

资料

hanlin 2015-07-30 12:02:31
认可0
吾问无为谓

Bingo403

0个粉丝

1

问答

0

专栏

0

资料

Bingo403 2016-03-09 14:07:41
认可0
学习下还是不错的

H伟伯爵H

0个粉丝

0

问答

0

专栏

0

资料

H伟伯爵H 2016-12-01 17:25:33
认可0
mark学习学习学习学习学习:lol

Ethan_ZSC

0个粉丝

0

问答

0

专栏

0

资料

Ethan_ZSC 2016-12-07 09:58:57
认可0
看代码有点吃不消,继续努力

rupert

0个粉丝

1

问答

0

专栏

0

资料

rupert 2017-04-03 15:49:04
认可0

学习下还是不错的

钓鱼大师

0个粉丝

1

问答

0

专栏

0

资料

钓鱼大师 2017-06-03 14:05:33
认可0
做算法的都是牛人啊
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
相关问答
无更多相似问答 去提问
举报反馈

举报类型

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

详细说明

易百纳技术社区