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

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

先看差分

             //移动窗口        
      [System.Runtime.InteropServices.DllImportAttribute("opencv_highgui2410.dll", EntryPoint = "cvMoveWindow")]
public static extern void cvMoveWindow([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string name, int x, int y);
//代表x帧差分,可以自由更改
static int USE_N_FRAMES_DIFF = ; public void PicDiff(string videoPath)
{
int iFrameIndex = ; IntPtr pIplGrayImg = IntPtr.Zero; IntPtr[] pIplFrameDiff = new IntPtr[USE_N_FRAMES_DIFF - ]; IntPtr[] pIplFrame = new IntPtr[USE_N_FRAMES_DIFF]; IntPtr CatchFrame = CvInvoke.cvCreateFileCapture(videoPath);
// 得到总帧数
var count = CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT);
// 视频宽度
int wd = (int)CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH);
// 视频高度
int hg = (int)CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT);
//// 当前帧位置
//CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES);
//// 帧频
CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS); CvInvoke.cvNamedWindow("source");
CvInvoke.cvNamedWindow("Out");
cvMoveWindow("source", , );
cvMoveWindow("Out", , );
IntPtr FrameImg; IntPtr rawImage = IntPtr.Zero;
rawImage = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, );
IntPtr pIplFrameDiffOr = IntPtr.Zero;
IntPtr pIplFrameDiffOrCC = IntPtr.Zero;
IntPtr pIplFrameSmooth = IntPtr.Zero;
pIplFrameDiffOr = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, );
pIplFrameDiffOrCC = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, );
pIplFrameSmooth = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, ); while ((FrameImg = CvInvoke.cvQueryFrame(CatchFrame)) != IntPtr.Zero)
{ Rectangle cr = CvInvoke.cvGetImageROI(FrameImg); pIplGrayImg = CvInvoke.cvCreateImage(cr.Size, Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, ); CvInvoke.cvCvtColor(FrameImg, pIplGrayImg, Emgu.CV.CvEnum.COLOR_CONVERSION.BGR2GRAY); CvInvoke.cvSaveImage(savename, pIplGrayImg, IntPtr.Zero);
pIplFrame[iFrameIndex % USE_N_FRAMES_DIFF] = pIplGrayImg; if (iFrameIndex >= USE_N_FRAMES_DIFF - )
{
for (int i = ; i < USE_N_FRAMES_DIFF - ; i++)
{ CvInvoke.cvAbsDiff(pIplFrame[i], pIplFrame[i + ], rawImage);
pIplFrameDiff[i] = rawImage;
CvInvoke.cvThreshold(pIplFrameDiff[i], pIplFrameDiff[i], , , Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY);
              //上面第三个参数为设置的阀值以此来根据物体运动时前后帧的差异产生白点
} for (int i = ; i < USE_N_FRAMES_DIFF - ; i++)
{
CvInvoke.cvOr(pIplFrameDiff[i], pIplFrameDiff[i + ], pIplFrameDiffOr, IntPtr.Zero); if (i + < USE_N_FRAMES_DIFF - )
{
CvInvoke.cvCopy(pIplFrameDiffOr, pIplFrameDiff[i + ], IntPtr.Zero);
} }
} CvInvoke.cvShowImage("source", FrameImg);
CvInvoke.cvShowImage("Out", pIplFrameDiffOr); CvInvoke.cvWaitKey();
iFrameIndex++; }
}

程序运行结果如图所示

高斯背景建模

      public void guassModel(string videoPath)
{
int iFrameIndex = ;
IntPtr CatchFrame = CvInvoke.cvCreateFileCapture(videoPath);
// 得到总帧数
var count = CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT);
// 视频宽度
int wd = (int)CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH);
// 视频高度
int hg = (int)CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT);
//// 帧频
CvInvoke.cvGetCaptureProperty(CatchFrame, Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS);
IntPtr background = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, );
IntPtr foreground = CvInvoke.cvCreateImage(new Size(wd, hg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, ); IntPtr FrameImg;
Emgu.CV.VideoSurveillance.BGStatModel<Bgr> bg = null;
CvInvoke.cvNamedWindow("bg");
CvInvoke.cvNamedWindow("fg");
CvInvoke.cvNamedWindow("source");
cvMoveWindow("bg", , );
cvMoveWindow("gf", , );
cvMoveWindow("source", , );
while ((FrameImg = CvInvoke.cvQueryFrame(CatchFrame)) != IntPtr.Zero)
{
Image<Bgr, byte> FramePic = new Image<Bgr, byte>(wd, hg);
CvInvoke.cvCopy(FrameImg, FramePic, IntPtr.Zero);
iFrameIndex++;
if (iFrameIndex == )
{
//高斯背景建模参数
Emgu.CV.Structure.MCvGaussBGStatModelParams pstruct = new MCvGaussBGStatModelParams();
pstruct.win_size = ;
pstruct.n_gauss = ;
pstruct.bg_threshold = 0.7;
pstruct.std_threshold = 3.5;
pstruct.minArea = ;
pstruct.weight_init = 0.333;
pstruct.variance_init = ;
bg = new Emgu.CV.VideoSurveillance.BGStatModel<Bgr>(FramePic, ref pstruct);
}
else
{
CvInvoke.cvShowImage("source", FrameImg);
CvInvoke.cvWaitKey();
//更新
bg.Update(FramePic);
background = bg.BackgroundMask;
CvInvoke.cvShowImage("bg", background);
CvInvoke.cvWaitKey();
foreground = bg.ForegroundMask;
CvInvoke.cvShowImage("fg", foreground);
CvInvoke.cvWaitKey();
}
}
CvInvoke.cvDestroyWindow("source");
CvInvoke.cvDestroyWindow("bg");
CvInvoke.cvDestroyWindow("fg");
}

运行结果如图

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

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

EmguCV学习——简单算法 差分与高斯的更多相关文章

  1. EmguCV学习——简单使用

    关于EmguCV我就不多说了,是对应于OpenCV的一套net库. 公司是视觉方面的业务,我又不会c++(好想会啊,正在学习中).由于各种需求,自己觉得对c++不是特别感冒,所以选用了net下的ope ...

  2. [置顶] 小白学习KM算法详细总结--附上模板题hdu2255

    KM算法是基于匈牙利算法求最大或最小权值的完备匹配 关于KM不知道看了多久,每次都不能完全理解,今天花了很久的时间做个总结,归纳以及结合别人的总结给出自己的理解,希望自己以后来看能一目了然,也希望对刚 ...

  3. 记录:EM 算法估计混合高斯模型参数

    当概率模型依赖于无法观测的隐性变量时,使用普通的极大似然估计法无法估计出概率模型中参数.此时需要利用优化的极大似然估计:EM算法. 在这里我只是想要使用这个EM算法估计混合高斯模型中的参数.由于直观原 ...

  4. 从 SGD 到 Adam —— 深度学习优化算法概览(一) 重点

    https://zhuanlan.zhihu.com/p/32626442 骆梁宸 paper插画师:poster设计师:oral slides制作人 445 人赞同了该文章 楔子 前些日在写计算数学 ...

  5. 学习cordic算法所得(流水线结构、Verilog标准)

    最近学习cordic算法,并利用FPGA实现,在整个学习过程中,对cordic算法原理.FPGA中流水线设计.Verilog标准有了更加深刻的理解. 首先,cordic算法的基本思想是通过一系列固定的 ...

  6. Javascript学习-简单测试环境

    Javascript学习-简单测试环境 在<JavaScript忍者秘籍>2.4测试条件基础知识中,作者给出了一个精简版的assert和assert组的实现,对于初学者而言,这无疑是一个很 ...

  7. 学习排序算法(一):单文档方法 Pointwise

    学习排序算法(一):单文档方法 Pointwise 1. 基本思想 这样的方法主要是将搜索结果的文档变为特征向量,然后将排序问题转化成了机器学习中的常规的分类问题,并且是个多类分类问题. 2. 方法流 ...

  8. CPD轮播广告库的简单算法

    在广告的领域中,有一种广告形式,采用的是CPD的售卖模式,为了对流量进行拆分,媒体方会对广告位进行轮播拆分.比如一个广告位,被拆成了10轮播,那么在广告主来预订广告位的时候,这个时候就可以告诉广告主, ...

  9. php实现简单算法2

    php实现简单算法2 去弄php手册,里面有数据结构,有数据结构就好办了,我的算法基础那么好. 而且的话有数据结构的话再配合我脑中的那些算法了,我就都ok啦. 在手册里面搜索php数据结构就好 路径如 ...

随机推荐

  1. maya user guider第一课,一些基本概念

    1.maya主要用于建模,动画, 视觉特效,游戏, 和模拟 一般分为以下几类: l  建模: ploygons, nurbs, subdivision surfaces   这是不同的建模方法. po ...

  2. Markdown 编辑器语法指南

    基本技巧 代码 如果你只想高亮语句中的某个函数名或关键字,可以使用 `function_name()` 实现 通常编辑器根据代码片段适配合适的高亮方法,但你也可以用 ``` 包裹一段代码,并指定一种语 ...

  3. javascript代码复用模式

    代码复用有一个著名的原则,是GoF提出的:优先使用对象组合,而不是类继承.在javascript中,并没有类的概念,所以代码的复用,也并不局限于类式继承.javascript中创建对象的方法很多,有构 ...

  4. 《Unix/Linux日志分析与流量监控》书稿完成

    <Unix/Linux日志分析与流量监控>书稿完成 近日,历时3年创作的75万字书稿已完成,本书紧紧围绕网络安全的主题,对各种Unix/Linux系统及网络服务日志进行了全面系统的讲解,从 ...

  5. C/C++中几种操作位的方法

    参考How do you set, clear and toggle a single bit in C? c/c++中对二进制位的操作包括设置某位为1.清除某位(置为0).开关某位(toggling ...

  6. nagios架构及windows,linux客户端配置

    Linux下Nagios的安装与配置 一.Nagios简介 Nagios是一款开源的电脑系统和网络监视工具,能有效监控Windows.Linux和Unix的主机状态,交换机路由器等网络设置,打印机等. ...

  7. c++ builder TListView控件按字符串排序(根据网上代码亲测ok)

    //--------------------------------------------------------------------------- /* 首先将一个列表框控件安放在Form上, ...

  8. 写给Node.js新手的7个小技巧

    一些我更愿意在开始就知道东西 利用 Node.js 开发是一个非常有趣,和令人满足的过程, 他有3万多个模块可以选择使用,并且所有的模块可以非常容易的集成入现有的应用之中. 无论如何,对于一些刚开始使 ...

  9. myeclipse关闭properties文件自动转义

    1.如图,源代码是这样: 2.保存后重新打开变成这样: 3.解决方法如下:

  10. sqlite3_exec函数的使用

    sqlite3_exec函数的使用 sqlite3数据库是一个小型的关系型的数据库,以文件的方式存在,打开文件即是打开数据库,它小巧且功能强大,在嵌入式领域内使用很广.现在就介绍一下其中一个重要函数的 ...