当观察场景的是一个固定的相机,背景几乎保持不变。在这种情况下,感兴趣的元素是在场景中运动的物体。为了提取出这些前景物体,我们需要对背景建模,然后将当前帧的模型与背景模型进行比较,以检测前景物体。这正是我们将要实现的,前景提取是智能监控应用的基础步骤。


实现方法:
如果我们能够获取当前场景背景的图像,那么通过简单的图像差分便可以提取出前景:

//计算当前图像与背景的差异
cv::absdiff(backgroundImage,currentImage,foreground);

差异足够大的像素都将被视为前景像素。
背景通常会随着时间变化,例如,从日出到日落之间光照条件会发生变化,同时新的物体可能会进入或离开背景。
因此我们必须能够动态创建背景的模型,这可以通过长时间观察场景来实现。
定期更新背景模型:通过计算滑动平均值,即对时序信号计算均值时考虑接收到的最新值。如果p(t)是t时刻的像素值,u(t-1)是当前的平均值,那么新的平均值将是 u(t)=(1-a)[u(t-1)]+ap(t) 参数a被称为学习率,它定义了当前值对平均值的影响程度。该值越大,滑动平均值对观察值的适应速度更快。
部分代码参考来源

// FeatureTracker.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <string>
#include <iomanip>using namespace cv;
using namespace std;//帧处理基类
class FrameProcessor
{
public:virtual void process(Mat &input,Mat &ouput)=0;
};  class BGFGSegmentor:public FrameProcessor
{  Mat gray;//当前帧灰度图  Mat background;//背景图,格式为32位浮点  Mat backImage;//CV_8U格式背景图  Mat foreground;//前景图  double learningRate;//学习率  int Thres;//阈值,滤去扰动
public:BGFGSegmentor():Thres(25),learningRate(0.2){}//帧处理函数  void process(Mat &frame,Mat &output){//转化为灰度图cvtColor (frame,gray,CV_BGR2GRAY);if(background.empty ())//第一帧gray.convertTo(background,CV_32F);  //背景转为CV_8U格式以便求取和当前帧差的绝对值background.convertTo(backImage,CV_8U);  //求当前帧与背景的差别  absdiff (backImage,gray,foreground);  //过滤掉前景中与背景差别不大的扰动点threshold(foreground,output,Thres,255,THRESH_BINARY_INV);  //更新背景,output作为掩码  accumulateWeighted (gray,background,learningRate,output);}
};  class VideoProcessor
{
private:VideoCapture caputure;  //写视频流对象  VideoWriter writer;  //输出文件名  string Outputfile;  int currentIndex;  int digits;  string extension;  FrameProcessor *frameprocessor;  //图像处理函数指针  void (*process)(Mat &,Mat &);  bool callIt;  string WindowNameInput;  string WindowNameOutput;  //延时  int delay;  long fnumber;  //第frameToStop停止  long frameToStop;  //暂停标志  bool stop;  //图像序列作为输入视频流  vector<string> images;  //迭代器
public:  VideoProcessor():callIt(true),delay(0),fnumber(0),stop(false),digits(0),frameToStop(-1){}//设置图像处理函数  void setFrameProcessor(void (*process)(Mat &,Mat &)){  frameprocessor = 0;  this->process = process;  CallProcess ();  }  //打开视频  bool setInput(string filename){  fnumber = 0;  //若已打开,释放重新打开  caputure.release ();  return caputure.open (filename);  }  //设置输入视频播放窗口  void displayInput(string wn){  WindowNameInput = wn;  namedWindow (WindowNameInput);  }  //设置输出视频播放窗口  void displayOutput(string wn){  WindowNameOutput = wn;  namedWindow (WindowNameOutput);  }  //销毁窗口  void dontDisplay(){  destroyWindow (WindowNameInput);  destroyWindow (WindowNameOutput);  WindowNameInput.clear ();  WindowNameOutput.clear ();  }  //启动  void run(){  Mat frame;  Mat output;  if(!isOpened())  return;  stop = false;  while(!isStopped()){  //读取下一帧  if(!readNextFrame(frame))  break;  if(WindowNameInput.length ()!=0)  imshow (WindowNameInput,frame);  //处理该帧  if(callIt){  if(process)  process(frame,output);  else if(frameprocessor)  frameprocessor->process (frame,output);  }  else{  output = frame;  }  if(Outputfile.length ()){  cvtColor (output,output,CV_GRAY2BGR);  writeNextFrame (output);  }  if(WindowNameOutput.length ()!=0)  imshow (WindowNameOutput,output);  //按键暂停,继续按键继续  if(delay>=0&&waitKey (delay)>=0)  waitKey(0);  //到达指定暂停键,退出  if(frameToStop>=0&&getFrameNumber()==frameToStop)  stopIt();  }  }  //暂停键置位  void stopIt(){  stop = true;  }  //查询暂停标志位  bool isStopped(){  return stop;  }  //返回视频打开标志  bool isOpened(){  return  caputure.isOpened ()||!images.empty ();  }  //设置延时  void setDelay(int d){  delay = d;  }  //读取下一帧  bool readNextFrame(Mat &frame){  if(images.size ()==0)  return caputure.read (frame);  else{  if(itImg!=images.end()){  frame = imread (*itImg);  itImg++;  return frame.data?1:0;  }  else  return false;  }  }  void CallProcess(){  callIt = true;  }  void  dontCallProcess(){  callIt = false;  }  //设置停止帧  void stopAtFrameNo(long frame){  frameToStop = frame;  }  // 获得当前帧的位置  long getFrameNumber(){  long fnumber = static_cast<long>(caputure.get ((CV_CAP_PROP_POS_FRAMES)));  return fnumber;  }  //获得帧大小  Size getFrameSize() {  if (images.size()==0) {  // 从视频流获得帧大小  int w= static_cast<int>(caputure.get(CV_CAP_PROP_FRAME_WIDTH));  int h= static_cast<int>(caputure.get(CV_CAP_PROP_FRAME_HEIGHT));  return Size(w,h);  }  else {  //从图像获得帧大小  cv::Mat tmp= cv::imread(images[0]);  return (tmp.data)?(tmp.size()):(Size(0,0));  }  }  //获取帧率  double getFrameRate(){  return caputure.get(CV_CAP_PROP_FPS);  }  vector<string>::const_iterator itImg;  bool setInput (const vector<string> &imgs){  fnumber = 0;  caputure.release ();  images = imgs;  itImg = images.begin ();  return true;  }  void  setFrameProcessor(FrameProcessor *frameprocessor){  process = 0;  this->frameprocessor = frameprocessor;  CallProcess ();  }  //获得编码类型  int getCodec(char codec[4]) {  if (images.size()!=0)  return -1;  union { // 数据结构4-char  int value;  char code[4];  } returned;  //获得编码值  returned.value= static_cast<int>(  caputure.get(CV_CAP_PROP_FOURCC));  // get the 4 characters  codec[0]= returned.code[0];  codec[1]= returned.code[1];  codec[2]= returned.code[2];  codec[3]= returned.code[3];  return returned.value;  }  bool setOutput(const string &filename,int codec = 0,double framerate = 0.0,bool isColor = true){  //设置文件名  Outputfile = filename;  //清空扩展名  extension.clear ();  //设置帧率  if(framerate ==0.0){  framerate = getFrameRate ();  }  //获取输入原视频的编码方式  char c[4];  if(codec==0){  codec = getCodec(c);  }  return writer.open(Outputfile,  codec,  framerate,  getFrameSize(),  isColor);  }  //输出视频帧到图片fileme+currentIndex.ext,如filename001.jpg  bool setOutput (const string &filename,//路径  const string &ext,//扩展名  int numberOfDigits=3,//数字位数  int startIndex=0 ){//起始索引  if(numberOfDigits<0)  return false;  Outputfile = filename;  extension = ext;  digits = numberOfDigits;  currentIndex = startIndex;  return true;  }  //写下一帧  void writeNextFrame(Mat &frame){  //如果扩展名不为空,写到图片文件中  if(extension.length ()){  stringstream ss;  ss<<Outputfile<<setfill('0')<<setw(digits)<<currentIndex++<<extension;  imwrite (ss.str (),frame);  }  //反之,写到视频文件中  else{  writer.write (frame);  }  }
};  int main(int argc, char *argv[])
{  VideoProcessor processor;  BGFGSegmentor segmentor;  //打开输入视频  processor.setInput ("walk.avi");  processor.displayInput ("Current Frame");  processor.displayOutput ("Output Frame");  //设置每一帧的延时  processor.setDelay (1000./processor.getFrameRate ());  //设置帧处理函数,可以任意  processor.setFrameProcessor (&segmentor);  processor.setOutput ("walkout",".avi");  processor.setOutput ("walkout",".jpg");  processor.run ();  return 0;
}  

提取视频中的前景物体相关推荐

  1. OpenCV实战——提取视频中的前景对象

    OpenCV实战--提取视频中的前景对象 0. 前言 1. 提取视频中的前景对象 2. 混合高斯方法 3. 完整代码 相关链接 0. 前言 当固定摄像机观察场景时,背景基本保持不变.在这种情况下,我们 ...

  2. 使用python moviepy提取视频中的音频,同时对音频数据进行数据可视化分析

    文章目录 1 使用moviepy库包提取音频 1.1 moviepy库包说明 1.2 安装moviepy 1.2 使用moviepy提取视频中的音频 2 使用librosa库包读取音频文件,并分析音频 ...

  3. python获取视频帧的时间_Python提取视频中图片的示例(按帧、按秒)

    一.按帧提取 #coding=utf-8 import os import cv2 def save_img(): #提取视频中图片 按照每帧提取 video_path = r'D:\\test\\' ...

  4. python提取txt中指定内容_提取视频中的音频——python三行程序搞定!

    写在开头   身处数据爆炸增长的时代,各种各样的数据都飞速增长,视频数据也不例外.我们可以使用 python 来提取视频中的音频,而这仅仅需要安装一个体量很小的python包,然后执行三行程序!    ...

  5. python 替换array中的值_利用Python提取视频中的字幕(文字识别)

    我的CSDN博客id:qq_39783601,昵称是糖潮丽子~辣丽 从今天开始我会陆续将数据分析师相关的知识点分享在这里,包括Python.机器学习.数据库等等. 今天来分享一个Python小项目! ...

  6. python从视频中提取音频_提取视频中的音频——python三行程序搞定!

    原标题:提取视频中的音频--python三行程序搞定! 写在开头 身处数据爆炸增长的时代,各种各样的数据都飞速增长,视频数据也不例外.我们可以使用 python 来提取视频中的音频,而这仅仅需要安装一 ...

  7. python 批量增加文件前缀_用python批量提取视频中的音频文件

    安装MoviePy pip3 install MoviePy 安装成功后需要打开MoviePy所在的文件夹 C:PythonLibsite-packagesmoviepy 打开config_defau ...

  8. python提取txt中指定内容_提取视频中的音频,Python三行程序搞定!

    来源:http://suo.im/5yOtbx 写在开头 身处数据爆炸增长的时代,各种各样的数据都飞速增长,视频数据也不例外.我们可以使用 python 来提取视频中的音频,而这仅仅需要安装一个体量很 ...

  9. python做视频抽帧图_Python提取视频中图片的示例(按帧、按秒)

    一.按帧提取 #coding=utf-8 import os import cv2 def save_img(): #提取视频中图片 按照每帧提取 video_path = r'd:\\test\\' ...

最新文章

  1. 温故而知新,ggplot2 饼图的几点笔记
  2. 本地连接出来的很慢解决方法
  3. OpenCV中图像水平拼接函数hconcat的使用
  4. 运行cmd状态下MySQL导入导出.sql文件
  5. html定位fix,html 定位fixed
  6. 容器编排技术 -- Kubernetes 调试 Service
  7. android 代码添加图片不显示,Android开发 从代码里设置Drawable图片不显示的问题
  8. CV Papers|计算机视觉论文推荐周报20200501期
  9. 哈工大计算机组织与体系结构实验二_小猿关注 | 计算机学院组织开展“新生入学实验室安全教育”主题活动...
  10. python需要下载哪些软件-80%的人都不知道,全球Python库下载前10名
  11. L2-012 关于堆的判断(模拟堆+字符串处理)
  12. 【numpy】数组增加一维(升维)小结
  13. 微信小程序的图片上传及图片预览功能
  14. HIGEN海坚驱动器维修FDA7045伺服变频器维修
  15. 【英语语法入门】 第31讲 [被动语态 (1)]被动态的构成和含义
  16. 游园惊梦--记游第九届软博会
  17. 一篇文章带你搞懂 JPA 和 hibernate
  18. Devoxx法国2012天3
  19. 编程语言php加密与解密的方法
  20. 全网最详细金融APP测试功能点-测试用例,详细整理(全)

热门文章

  1. 元器件的温度特性(电容、电感、晶振等)
  2. ESP8266_21基于ESP8266的一键配网
  3. 数组排序sort()。升序还是降序
  4. API工具栏教你如何采集淘宝拼多多商品详情数据
  5. 交换机SNMP V3版本配置
  6. c++ HDU 1279 士兵队列训练问题
  7. 干掉保险丝和继电器,自动驾驶才能更安全
  8. 【NGUI】Unity实现英雄联盟选择皮肤效果
  9. 9.ESP32--ADC
  10. 爱普生L4158使用评测及小白智慧打印离线解决办法