提取视频中的前景物体
当观察场景的是一个固定的相机,背景几乎保持不变。在这种情况下,感兴趣的元素是在场景中运动的物体。为了提取出这些前景物体,我们需要对背景建模,然后将当前帧的模型与背景模型进行比较,以检测前景物体。这正是我们将要实现的,前景提取是智能监控应用的基础步骤。
实现方法:
如果我们能够获取当前场景背景的图像,那么通过简单的图像差分便可以提取出前景:
//计算当前图像与背景的差异
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;
}
提取视频中的前景物体相关推荐
- OpenCV实战——提取视频中的前景对象
OpenCV实战--提取视频中的前景对象 0. 前言 1. 提取视频中的前景对象 2. 混合高斯方法 3. 完整代码 相关链接 0. 前言 当固定摄像机观察场景时,背景基本保持不变.在这种情况下,我们 ...
- 使用python moviepy提取视频中的音频,同时对音频数据进行数据可视化分析
文章目录 1 使用moviepy库包提取音频 1.1 moviepy库包说明 1.2 安装moviepy 1.2 使用moviepy提取视频中的音频 2 使用librosa库包读取音频文件,并分析音频 ...
- python获取视频帧的时间_Python提取视频中图片的示例(按帧、按秒)
一.按帧提取 #coding=utf-8 import os import cv2 def save_img(): #提取视频中图片 按照每帧提取 video_path = r'D:\\test\\' ...
- python提取txt中指定内容_提取视频中的音频——python三行程序搞定!
写在开头 身处数据爆炸增长的时代,各种各样的数据都飞速增长,视频数据也不例外.我们可以使用 python 来提取视频中的音频,而这仅仅需要安装一个体量很小的python包,然后执行三行程序! ...
- python 替换array中的值_利用Python提取视频中的字幕(文字识别)
我的CSDN博客id:qq_39783601,昵称是糖潮丽子~辣丽 从今天开始我会陆续将数据分析师相关的知识点分享在这里,包括Python.机器学习.数据库等等. 今天来分享一个Python小项目! ...
- python从视频中提取音频_提取视频中的音频——python三行程序搞定!
原标题:提取视频中的音频--python三行程序搞定! 写在开头 身处数据爆炸增长的时代,各种各样的数据都飞速增长,视频数据也不例外.我们可以使用 python 来提取视频中的音频,而这仅仅需要安装一 ...
- python 批量增加文件前缀_用python批量提取视频中的音频文件
安装MoviePy pip3 install MoviePy 安装成功后需要打开MoviePy所在的文件夹 C:PythonLibsite-packagesmoviepy 打开config_defau ...
- python提取txt中指定内容_提取视频中的音频,Python三行程序搞定!
来源:http://suo.im/5yOtbx 写在开头 身处数据爆炸增长的时代,各种各样的数据都飞速增长,视频数据也不例外.我们可以使用 python 来提取视频中的音频,而这仅仅需要安装一个体量很 ...
- python做视频抽帧图_Python提取视频中图片的示例(按帧、按秒)
一.按帧提取 #coding=utf-8 import os import cv2 def save_img(): #提取视频中图片 按照每帧提取 video_path = r'd:\\test\\' ...
最新文章
- 温故而知新,ggplot2 饼图的几点笔记
- 本地连接出来的很慢解决方法
- OpenCV中图像水平拼接函数hconcat的使用
- 运行cmd状态下MySQL导入导出.sql文件
- html定位fix,html 定位fixed
- 容器编排技术 -- Kubernetes 调试 Service
- android 代码添加图片不显示,Android开发 从代码里设置Drawable图片不显示的问题
- CV Papers|计算机视觉论文推荐周报20200501期
- 哈工大计算机组织与体系结构实验二_小猿关注 | 计算机学院组织开展“新生入学实验室安全教育”主题活动...
- python需要下载哪些软件-80%的人都不知道,全球Python库下载前10名
- L2-012 关于堆的判断(模拟堆+字符串处理)
- 【numpy】数组增加一维(升维)小结
- 微信小程序的图片上传及图片预览功能
- HIGEN海坚驱动器维修FDA7045伺服变频器维修
- 【英语语法入门】 第31讲 [被动语态 (1)]被动态的构成和含义
- 游园惊梦--记游第九届软博会
- 一篇文章带你搞懂 JPA 和 hibernate
- Devoxx法国2012天3
- 编程语言php加密与解密的方法
- 全网最详细金融APP测试功能点-测试用例,详细整理(全)