EmguCV学习——简单算法 差分与高斯

公司项目需要检测运动物体,我对opencv也没啥研究,google了好久看了好多方法,最简单的就是差分与高斯背景建模了。

旁边搞c++的同事正在搞更nb的算法,等出来了 我再转成C#版的分享。

先看差分

 1             //移动窗口        
      [System.Runtime.InteropServices.DllImportAttribute("opencv_highgui2410.dll", EntryPoint = "cvMoveWindow")]
 2         public static extern void cvMoveWindow([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string name, int x, int y);
 3         //代表x帧差分,可以自由更改
 4         static int USE_N_FRAMES_DIFF = 10;
 5 
 6         public void PicDiff(string videoPath)
 7         {
 8             int iFrameIndex = 0;
 9 
10             IntPtr pIplGrayImg = IntPtr.Zero;
11 
12             IntPtr[] pIplFrameDiff = new IntPtr[USE_N_FRAMES_DIFF - 1];
13 
14             IntPtr[] pIplFrame = new IntPtr[USE_N_FRAMES_DIFF];
15 
16             IntPtr CatchFrame = CvInvoke.cvCreateFileCapture(videoPath);
17             // 得到总帧数
18             var count = CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT);
19             // 视频宽度
20             int wd = (int)CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH);
21             // 视频高度
22             int hg = (int)CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT);
23             //// 当前帧位置
24             //CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES);
25             //// 帧频
26             CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS);
27 
28             CvInvoke.cvNamedWindow("source");
29             CvInvoke.cvNamedWindow("Out");
30             cvMoveWindow("source", 0, 0);
31             cvMoveWindow("Out", 0, 350);
32             IntPtr FrameImg;
33 
34             IntPtr rawImage = IntPtr.Zero;
35             rawImage = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1);
36             IntPtr pIplFrameDiffOr = IntPtr.Zero;
37             IntPtr pIplFrameDiffOrCC = IntPtr.Zero;
38             IntPtr pIplFrameSmooth = IntPtr.Zero;
39             pIplFrameDiffOr = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1);
40             pIplFrameDiffOrCC = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1);
41             pIplFrameSmooth = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1);
42 
43             while ((FrameImg = CvInvoke.cvQueryFrame(CatchFrame)) != IntPtr.Zero)
44             {
45                
46                 Rectangle cr = CvInvoke.cvGetImageROI(FrameImg);
47 
48                 pIplGrayImg = CvInvoke.cvCreateImage(cr.Size, Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1);
49                 
50                 CvInvoke.cvCvtColor(FrameImg, pIplGrayImg, Emgu.CV.CvEnum.COLOR_CONVERSION.BGR2GRAY);
51 
52                 CvInvoke.cvSaveImage(savename, pIplGrayImg, IntPtr.Zero);
53                 pIplFrame[iFrameIndex % USE_N_FRAMES_DIFF] = pIplGrayImg;
54 
55                 if (iFrameIndex >= USE_N_FRAMES_DIFF - 1)
56                 {
57                     for (int i = 0; i < USE_N_FRAMES_DIFF - 1; i++)
58                     {
59 
60                         CvInvoke.cvAbsDiff(pIplFrame[i], pIplFrame[i + 1], rawImage);
61                         pIplFrameDiff[i] = rawImage;
62                         CvInvoke.cvThreshold(pIplFrameDiff[i], pIplFrameDiff[i], 20, 255, Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY);
63               //上面第三个参数为设置的阀值以此来根据物体运动时前后帧的差异产生白点
64                     }
65 
66                     for (int i = 0; i < USE_N_FRAMES_DIFF - 2; i++)
67                     {
68                         CvInvoke.cvOr(pIplFrameDiff[i], pIplFrameDiff[i + 1], pIplFrameDiffOr, IntPtr.Zero);
69 
70                         if (i + 1 < USE_N_FRAMES_DIFF - 2)
71                         {
72                             CvInvoke.cvCopy(pIplFrameDiffOr, pIplFrameDiff[i + 1], IntPtr.Zero);
73                         }
74 
75                     }
76                 }
77                 
78 
79                 CvInvoke.cvShowImage("source", FrameImg);
80                 CvInvoke.cvShowImage("Out", pIplFrameDiffOr);
81                
82                 CvInvoke.cvWaitKey(1);
83                 iFrameIndex++;
84 
85             } 
86 }                                        

程序运行结果如图所示

高斯背景建模

 1      public void guassModel(string videoPath)
 2       {   
 3             int iFrameIndex = 0;
 4             IntPtr CatchFrame = CvInvoke.cvCreateFileCapture(videoPath);
 5             // 得到总帧数
 6             var count = CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT);
 7             // 视频宽度
 8             int wd = (int)CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH);
 9             // 视频高度
10             int hg = (int)CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT);
11             //// 帧频
12             CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS);
13             IntPtr background = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1);
14             IntPtr foreground = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1);
15 
16             IntPtr FrameImg;
17             Emgu.CV.VideoSurveillance.BGStatModel<Bgr> bg = null;
18             CvInvoke.cvNamedWindow("bg");
19             CvInvoke.cvNamedWindow("fg");
20             CvInvoke.cvNamedWindow("source");
21             cvMoveWindow("bg", 400, 0);
22             cvMoveWindow("gf", 800, 0);
23             cvMoveWindow("source", 0, 0);
24             while ((FrameImg = CvInvoke.cvQueryFrame(CatchFrame)) != IntPtr.Zero)
25             {
26                 Image<Bgr, byte> FramePic = new Image<Bgr, byte>(wd, hg);
27                 CvInvoke.cvCopy(FrameImg, FramePic, IntPtr.Zero);
28                 iFrameIndex++;
29                 if (iFrameIndex == 1)
30                 {
31                     //高斯背景建模参数
32                     Emgu.CV.Structure.MCvGaussBGStatModelParams pstruct = new MCvGaussBGStatModelParams();
33                     pstruct.win_size = 50;
34                     pstruct.n_gauss = 3;
35                     pstruct.bg_threshold = 0.7;
36                     pstruct.std_threshold = 3.5;
37                     pstruct.minArea = 100; 
38                     pstruct.weight_init = 0.333;
39                     pstruct.variance_init = 30;
40                     bg = new Emgu.CV.VideoSurveillance.BGStatModel<Bgr>(FramePic, ref pstruct);
41                 }
42                 else
43                 {
44                     CvInvoke.cvShowImage("source", FrameImg);
45                     CvInvoke.cvWaitKey(10);
46                     //更新
47                     bg.Update(FramePic);
48                     background = bg.BackgroundMask;
49                     CvInvoke.cvShowImage("bg", background);
50                     CvInvoke.cvWaitKey(10);
51                     foreground = bg.ForegroundMask;
52                     CvInvoke.cvShowImage("fg", foreground);
53                     CvInvoke.cvWaitKey(10);
54                 }
55             }
56             CvInvoke.cvDestroyWindow("source");
57             CvInvoke.cvDestroyWindow("bg");
58             CvInvoke.cvDestroyWindow("fg");
59         }            

运行结果如图

高斯的缺点就是受光照影响太大,近距离效果不好。

种一棵树最好的时间是十年前,其次是现在。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏闻道于事

js登录滑动验证,不滑动无法登陆

js的判断这里是根据滑块的位置进行判断,应该是用一个flag判断 <%@ page language="java" contentType="text/html...

1.2K8
来自专栏菩提树下的杨过

利用ActiveX实现web页面设置本地默认打印机、纸张大小

通常web技术无法设置本地计算机的默认打印机,包括用代码设置纸张大小,如果业务系统中真遇到这种需求,只能通过其它辅助手段(比如ActiveX)实现。下面这段代码...

3001
来自专栏跟着阿笨一起玩NET

c#实现打印功能

6702
来自专栏叁金大数据

EmguCV学习——视频与图片互转

其实视频转图片在上篇文章中已经有些眉目了,其实就是按帧读取视频,然后把帧保存就ok。然后自己再加个进度条美化一下。。。这代码简单易懂,还是直接上代码吧。

2581
来自专栏小狼的世界

惊闻NBC在奥运后放弃使用Silverlight

奥运初始的时候,媒体对于NBC使用Silverlight技术进行了高调的宣传,没想到奥运会结束刚刚三周的时间,NBC就弃用了Siverlight,重新采用Ado...

1222
来自专栏跟着阿笨一起玩NET

TabControl控件的美化

文件下载:http://files.cnblogs.com/zfanlong1314/TabControlEX.rar

4702
来自专栏PPV课数据科学社区

【学习】七天搞定SAS(三):基本模块调用

搞定基本的函数之后,开始鼓捣SAS里面的模型。也就是说,要开始写PROC了。说实话,越学SAS,越觉得SAS像Stata...无论是从输出的样式,还是语法。好不...

3395
来自专栏Hongten

My Notepad

I have spent near more two weeks to write this Notepad application. At this mome...

1282
来自专栏技术之路

用 WPF 写的颜色拾取器

之前都是用别人的颜色拾取器,今天自己用WPF写了一个颜色拾取器小程序 拾取鼠标所在位置的颜色,按键盘上的空格键停止取色 程序下载:MyWPFScreenColo...

2887
来自专栏菩提树下的杨过

PixelBender(着色器)初体验

只要是玩过photoshop的人,一定会对ps中的各式各样、功能强大的滤镜(filter)留下深刻的印象。 Adobe是靠图形处理软件起家的,这方面一直是它的强...

2966

扫码关注云+社区

领取腾讯云代金券