OpenCV温故而知新: 入侵侦测 2


应用场景

入侵侦测通常可被广泛用于诸如禁行区域的非法进入,如:私家住宅、限制区域、军事区的非法进入等情景。检测对象为人物。

工作原理

预先设置一条线性区域,然后在该区域内检测移动人物,看是否有人物穿越。

补充说明

本算法容易受到穿越人物大小及穿越角度的影响,人体大小参数可设,但若是设置过大容易检测不到小物体,设置过小,则容易误报。通常需配合警报录像来工作,以实现实时的检测和事后的排查及过滤。注意:镜头视野(焦距)的大小也会影响检测的准确度。

使用者操作:
1.在视窗点选实体围墙的上面两角(顺序:左→右)
2.调整Threshold的大小:如果产生的FG杂讯太多,此时可以试着调高Threshold
3.调整pattern的大小:尽量让蓝色框包含整个人形

影片场景预设:
1.实体围墙,墙高至少要到成年人肩膀以上
2.摄影机的拍摄角度和围墙的法向量夹角不能超过45度以上
3.摄影机架设的高度约2.5公尺至3.5公尺左右
4.调整实体围墙分隔线最好是在画面1/2处左右

以下是接口说明。

全域类别说明:

struct Object

{

bool existFlag ;                        //使用 0 no 1 yes

int missedFrame;                            //追丢的frame数

int grade;                                        //跟追踪到的物体距离分数

CvPoint mean[200];                //轨迹点

}

class IntruderDetect

{

private:

CvPoint pt0,pt1,pt2,pt3;          //绘图时使用

IplImage*    templ              ;    //人的pattern

IplImage*    hsv                ;    //当前的frame

IplImage*    newbg_model        ;   //一开始的背景

IplImage*    templ_new          ;    //scale之后新的pattern

IplImage*    backgroundImg      ;    //更新过后的背景

IplImage*    backgroundImgModel ;    //背景相减时使用

IplImage*    foregroundImg      ;    //前景 Gray Level

IplImage*    result             ;     //pattern比对的结果

IplImage*    trace              ;     //轨迹

IplImage *   reBGRImg          ;    //前景 BGR

IplImage *mask                 ;    //屏蔽

int a,b,FrameNum;             //in 人数 , out 人数 ,第几张frame

int p,i,j,tmpCounte,;                //  用于回圈

int nWidth,nHeight,chnal,nWidthStep;    //读入影像的宽.高.频道

int x1, y1, x2, y2;                     //定义的line

double nA,nB;                    //y=nA*x+nB

CvRect nrect;                //set ROI

bool system_on;              //开始数人数

bool SetThreshold_on;         //人的大小,背景参数设定完成

bool SetRoi_on;              //ROI设定完成

int block_x1[10],block_y1[10],block_x2[10],block_y2[10];

//存框框左上及右下坐标

float nscale;                  //pattern scale的大小

int nthreshold;                 //背景相减的threshold

int center_x[1000],center_y[1000], CenterNum;

//每个pattern比对到的中心 以及个数

int ptr[10];                          //轨迹中有几个转折点

public:

struct Object humanObj[10];            //宣告10个物体

IntruderDetect(int width, int height,int nChannels,int widthStep);

~IntruderDetect();

SetThreshold(float scale,int threshold ); //读取人的大小及背景参数的值

SetRoi(int rx,int ry,int rw,int rh); //读取设定的ROI范围

SetRoad(int p_x0,int p_y0,int p_x1,int p_y1,int p_x2,int p_y2,int p_x3,int p_y3);

loadtempl();                         //读取pattern

loadframe(IplImage*  tmp_frame);  //读取当前frame

subimage();                         //背景相减

Template_Match();                    //比对人型样板

GetPoint(int t,int k);       //读取框人的坐标    可以不读取

//t从0到10代表每张frame画框的次数,最多10个

//K=1时读取左上x坐标

//K=2时读取左上y坐标

//K=3时读取右下x坐标

//K=4时读取右下y坐标

ResetPoint();            //reset框人的坐标

//使用GetPoint(int t,int k)  时一定要用

getInOut(int k);        // k=1取得in 人数 , k=2取得out 人数

resetInOut();                        //人数归零

IplImage* GetImage(int imgnum);       //回传最后结果

//Imgnum=1 回传当前frame

//Imgnum=2 回传前景

//Imgnum=3 回传轨迹

releaseimage();                      //释放所有内存空间

};

成员函式说明

IntruderDetect::IntruderDetect(int width, int height,int nChannels,int widthStep){          

目的:

initial all variables we’ll use the program

方法:

set all variable will use

参数:

Parameter

Type

Description

width

int

frame的宽

height

int

frame的高

nChannels

int

frame的channels

widthStep

int

输入影像widthStep

}

IntruderDetect::~IntruderDetect(){                                                     

目的: 释放宣告的内存空间

}

IntruderDetect::SetThreshold(float scale,int threshold){                                             

目的:

将pattern的大小及背景参数读入

方法:

将pattern的大小读入及背景参数读入,完成后SetThreshold_on设为true

参数:

 

Parameter

Type

Description

scale

float

pattern的大小

threshold

int

背景参数

}

IntruderDetect::SetRoi(int rx,int ry,int rw,int rh){                                                   

目的:

产生搜索人的region

方法:

针对围墙内部范围的移动物体做侦测,完成后SetRoi_on 设为true

参数:

Parameter

Type

Description

rx

int

ROI左上角x坐标

ry

int

ROI左上角y坐标

rw

int

ROI的宽

rh

int

ROI的高

}

IntruderDetect::SetRoad(int p_x0,int p_y0,int p_x1,int p_y1,int p_x2,int p_y2,int p_x3,int p_y3){ 

目的:

获得分界线斜率信息

方法:

取得围墙的四个点的信息,由左上和右上两点得到这两点连乘一线的斜率,完成后SetRoad_on 设为true

参数:

Parameter

Type

Description

p_x0

int

围墙左上角x坐标

p_y0

int

围墙左上角y坐标

p_x1

int

围墙右上角x坐标

p_y1

int

围墙右上角y坐标

p_x2

int

围墙右下角x坐标

p_y2

int

围墙右下角y坐标

p_x3

int

围墙左下角x坐标

p_x3

int

围墙左下角y坐标

}

IntruderDetect::loadtempl(){                                                                   

目的:读取body pattern

}

IntruderDetect:: subimage()                                                           

目的:

建立foreground

方法:

直接将hsv、backgroundImg作背景相减,并搭配threshold来产生前景影像,放置于foregroundImg的内存指针区块内

}

IntruderDetect:Template_Match()                                                       

目的:

利用人形模型跟前景比对,当入侵者在翻墙时产生形变时,这成为我们判定是否爬墙的依据之一

方法:

建立新pattern,设定result(pattern比对结果)的大小,建立ROI后开始比对,将比对结果高的区域框起来后,覆盖掉附近区域并将中心点存入center_x , center_y ,CenterNum++,最后释放result、templ_new

}

IntruderDetect:: loadframe(IplImage*    tmp_frame)                                    

目的:

把video读进来做处理

方法:

1.背景相减得到foreground=> subimage()

2.开始做比对=> Template_Match()

3.判断框框之间的关系,若有物体出现跟先前的物体作比对

4.当物体轨迹存在且missedframe大于7时,判断其轨迹是否进入或离开(计数进出人数),完成后清除轨迹

参数:

 

Parameter

Type

Description

tmp_frame

IplImage

输入来源影像

}

IntruderDetect:: getInOut(int k){                                                        

目的:

得到穿越围墙进出人数

方法:

当k=1回传穿越围墙进来人数;当k=2回传穿越围墙出去人数

参数:

 

Parameter

Type

Description

k

int

回传穿越围墙进出人数的判断

}

IntruderDetect::GetPoint(int t,int k){                                                     

目的:

得到画框的点坐标

方法:

k=1时读取左上x坐标;k=2时读取左上y坐标;k=3时读取右下x坐标;k=4时读取右下y坐标

参数:

 

Parameter

Type

Description

t

int

从0到10代表每张frame画框的次数,最多10个

k

int

读取坐标的选择

}

IntruderDetect::ResetPoint(){                                                          

目的:

将所有框框坐标归零

}

IntruderDetect:: resetInOut()                                                           

目的:

入侵人数归零

}

IntruderDetect:: releaseimage()                                                        

目的:

Release variables and storage

}

IplImage* IntruderDetect:: GetImage(int imgnum)                                       

目的:

回传影像数据

方法:

imgnum=1=>回传当前影像;imgnum=2 =>回传前景;imgnum=3 =>回传轨迹

参数:

 

Parameter

Type

Description

imgnum

int

判断回传影像数据

}

测试程序及序列

测试程序: http://rg4.net/p/easyiv/libintruderdetect_test.7z

测试视频序列:http://rg4.net/p/easyiv/libintruderdetect_sample.avi

测试程序说明:

  • 指定测试视频:libintruderdetect_test.exe 111.avi,这个111.avi是你输入的视频文件。若不指定则默认打开当前目录下的libintruderdetect_sample.avi文件,若这个文件不存在则打开电脑上的摄像头。
  • 开始后请先通过鼠标拖拉点选设置警戒线。具体如下图。
  • 附带文件:man.bmp,请将其与程序放在同一目录下使用。
  • 测试程序快捷键:按r重新设定ROI检测区域,按p暂停处理,按t or ESC键中止。
EasyIV - Intruder Detect snapshot
EasyIV – Intruder Detect snapshot

Leave a comment

Your email address will not be published. Required fields are marked *

2 thoughts on “OpenCV温故而知新: 入侵侦测

  • 彭志勇

    韦老师:

        您好!我是山东大学控制科学与工程学院一名研一的学生,我的导师是常发亮教授,我的研究方向是模式识别与智能系统,目前研究视频监控,现在正在完善入侵侦测这一功能,我对您在这方面的工作非常感兴趣,可以把您关于入侵侦测的源代码供我参考一下吗?

        谢谢!

                                                  彭志勇

                                          山东大学模式识别实验室

    • Jacky Wei Post author

      彭志勇,你好,入侵侦测的实现原理其实很简单,而且其基础源代码在opencv的示例程序下就有提供,建议你好好看看opencv的示例程序的代码,相信会对你的研究和学习会有很大帮助的。