前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >EmguCV学习——简单算法 差分与高斯

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

作者头像
叁金
发布2018-09-04 14:52:11
8020
发布2018-09-04 14:52:11
举报
文章被收录于专栏:叁金大数据叁金大数据

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

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

先看差分

代码语言:javascript
复制
 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 }                                        

程序运行结果如图所示

高斯背景建模

代码语言:javascript
复制
 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         }            

运行结果如图

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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-08-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档