目录
最近手边的零食总是莫名其妙的减少,为了抓到一个元凶来帮我续零食,就想着使用手边的usb摄像头来实现一个动态物体监测和保存视频的功能,不过这里使用最简单的帧差法来实现物体的运动监测。
运动物体图像在相邻两帧间差别较大,两帧差值后进行简单的图像处理,较容易判断是否存在物体移动,类似于剪纸动画,本例中使用帧差后判断阈值分割后的面积来确定是否存在物体运动。帧差法用前一帧图像作为当前帧的背景模型具有较好的实时性,其背景不积累,且更新速度快、算法简单、计算量小。算法的不足在于对环境噪声较为敏感,阈值的选择相当关键,选择过低不足以抑制图像中的噪声,过高则忽略了图像中有用的变化。对于比较大的、颜色一致的运动目标,有可能在目标内部产生空洞,无法完整地提取运动目标。
将当前帧图像和上一帧图像进行灰度化,然后高斯滤波后做图像差值,选定合适的二值化阈值分割,最后对分割处理的区域面积进行判定。
Mat grayframePre,frameDet;
Mat frameNow,grayframeNow;
cvtColor(matFrame,grayframeNow,COLOR_RGB2GRAY);
cvtColor(framePre,grayframePre,COLOR_RGB2GRAY);
GaussianBlur(grayframeNow,grayframeNow,Size(21,21),0,0);
GaussianBlur(grayframePre,grayframePre,Size(21,21),0,0);
absdiff(grayframeNow,grayframePre,frameDet);
framePre = matFrame;
threshold(frameDet,frameDet,20,255,THRESH_BINARY);
Mat element = getStructuringElement(0,Size(3,3));
vector<vector<Point>> contours;
dilate(frameDet,frameDet,element);
findContours(frameDet,contours,RETR_TREE,CHAIN_APPROX_SIMPLE,Point());
qDebug()<<"Num"<<contours.size();
QString SavePath = "D:/ImgPath/" + QString::number(VideoNum) + "_track.avi";
if(contours.size()==0)
{
if(writer.isOpened())
{
writer.release();
}
if(isSaveFrame)
{
isSaveFrame = false;
VideoNum++;
}
}
else
{
for(int i=0;i<contours.size();i++)
{
double area = contourArea(contours[i]);
if(area < 100)continue;
else
{
qDebug()<<"有物体运动!";
if(!isSaveFrame)
{
int fourcc = writer.fourcc('M', 'J', 'P', 'G');
writer.open(SavePath.toStdString(),fourcc,10,Size(frameWidth,frameHeight),true);
isSaveFrame = true;
}
else
{
writer.write(matFrame);
}
break;
}
}
}
}
else
{
framePre = matFrame;
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "opencv2/opencv.hpp"
#include <QTimer>
using namespace cv;
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_btnOpenVedio_clicked();
void on_btnQuit_clicked();
void readFrame();
void on_ckb_Track_clicked(bool checked);
private:
Ui::Widget *ui;
bool openCam;
bool isTrack=false;
bool isSaveFrame = false;
QTimer *timer;
VideoCapture *cap;
Mat framePre;
int fps,frameWidth,frameHeight;
VideoWriter writer;
int VideoNum = 0;
//Mat转换QImage
QImage cvMat2QImage(const cv::Mat& mat);
};
#endif // WIDGET_H
widget.cpp
#pragma execution_character_set("utf-8")
#include "widget.h"
#include "ui_widget.h"
#include <iostream>
#include <QDebug>
using namespace std;
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
timer = new QTimer(this);
timer->stop();
connect(timer,SIGNAL(timeout()),this,SLOT(readFrame()));
openCam = true;
cap = new VideoCapture(0);
frameWidth = cap->get(CAP_PROP_FRAME_WIDTH);
frameHeight = cap->get(CAP_PROP_FRAME_HEIGHT);
fps = cap->get(CAP_PROP_FPS);
qDebug()<<"width"<<frameWidth<<frameHeight<<fps;
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_btnOpenVedio_clicked()
{
if(openCam)
{
ui->btnOpenVedio->setText("关闭摄像头");
timer->start(30);
}
else {
ui->btnOpenVedio->setText("打开摄像头");
timer->stop();
}
openCam = !openCam;
}
QImage Widget::cvMat2QImage(const cv::Mat &mat)
{
switch ( mat.type() )
{
// 8-bit 4 channel
case CV_8UC4:
{
QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_RGB32 );
return image;
}
// 8-bit 3 channel
case CV_8UC3:
{
QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_RGB888 );
return image.rgbSwapped();
}
// 8-bit 1 channel
case CV_8UC1:
{
static QVector<QRgb> sColorTable;
// only create our color table once
if ( sColorTable.isEmpty() )
{
sColorTable.resize( 256 );
for ( int i = 0; i < 256; ++i )
{
sColorTable[i] = qRgb( i, i, i );
}
}
QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_Indexed8 );
image.setColorTable( sColorTable );
return image;
}
default:
qDebug("Image format is not supported: depth=%d and %d channels\n", mat.depth(), mat.channels());
qWarning() << "cvMatToQImage - cv::Mat image type not handled in switch:" << mat.type();
break;
}
return QImage();
}
void Widget::on_btnQuit_clicked()
{
timer->stop();
cap->release();
close();
}
void Widget::readFrame()
{
Mat matFrame;
cap->read(matFrame);
if(isTrack)
{
Mat grayframePre,frameDet;
Mat frameNow,grayframeNow;
cvtColor(matFrame,grayframeNow,COLOR_RGB2GRAY);
cvtColor(framePre,grayframePre,COLOR_RGB2GRAY);
GaussianBlur(grayframeNow,grayframeNow,Size(21,21),0,0);
GaussianBlur(grayframePre,grayframePre,Size(21,21),0,0);
absdiff(grayframeNow,grayframePre,frameDet);
framePre = matFrame;
threshold(frameDet,frameDet,20,255,THRESH_BINARY);
Mat element = getStructuringElement(0,Size(3,3));
vector<vector<Point>> contours;
dilate(frameDet,frameDet,element);
findContours(frameDet,contours,RETR_TREE,CHAIN_APPROX_SIMPLE,Point());
qDebug()<<"Num"<<contours.size();
QString SavePath = "D:/ImgPath/" + QString::number(VideoNum) + "_track.avi";
if(contours.size()==0)
{
if(writer.isOpened())
{
writer.release();
}
if(isSaveFrame)
{
isSaveFrame = false;
VideoNum++;
}
}
else
{
for(int i=0;i<contours.size();i++)
{
double area = contourArea(contours[i]);
if(area < 100)continue;
else
{
qDebug()<<"有物体运动!";
if(!isSaveFrame)
{
int fourcc = writer.fourcc('M', 'J', 'P', 'G');
writer.open(SavePath.toStdString(),fourcc,10,Size(frameWidth,frameHeight),true);
isSaveFrame = true;
}
else
{
writer.write(matFrame);
}
break;
}
}
}
}
else
{
framePre = matFrame;
}
QImage Qimg = cvMat2QImage(matFrame);
ui->picshow->setPixmap(QPixmap::fromImage(Qimg));
}
void Widget::on_ckb_Track_clicked(bool checked)
{
if(checked)
{
isTrack = true;
}
else {
isTrack = false;
}
}

打开摄像头后,可以进行采集视频操作,勾选“打开追踪”,程序会调用帧差算法判定是否有运动物体,如果有物体运动,就保存运动时的视频。

首先,两帧差是比较基础的检测运动物体的方法,虽然其运算速度快,但其无法过滤光照或微小抖动的干扰,而且运动目标会出现“重影”导致出现内部空洞。三帧差法是在相邻帧差法基础上改进的算法,在一定程度上优化了运动物体双边,粗轮廓的现象,相比之下,三帧差法比相邻帧差法更适用于物体移动速度较快的情况,比如道路上车辆的智能监控。
我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby数组,我们在StackOverflow上找到一
当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?
之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m
之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶
我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions
在前面两节的例子中,主界面窗口的尺寸和标签控件显示的矩形区域等,都是用C++代码编写的。窗口和控件的尺寸都是预估的,控件如果多起来,那就不好估计每个控件合适的位置和大小了。用C++代码编写图形界面的问题就是不直观,因此Qt项目开发了专门的可视化图形界面编辑器——QtDesigner(Qt设计师)。通过QtDesigner就可以很方便地创建图形界面文件*.ui,然后将ui文件应用到源代码里面,做到“所见即所得”,大大方便了图形界面的设计。本节就演示一下QtDesigner的简单使用,学习拖拽控件和设置控件属性,并将ui文件应用到Qt程序代码里。使用QtDesigner设计界面在开始菜单中找到「Q
动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、
2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p
Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图
目前我正在使用这个正则表达式从YoutubeURL中提取视频ID:url.match(/v=([^&]*)/)[1]我怎样才能改变它,以便它也可以从这个没有v参数的YoutubeURL获取视频ID:http://www.youtube.com/user/SHAYTARDS#p/u/9/Xc81AajGUMU感谢阅读。编辑:我正在使用ruby1.8.7 最佳答案 对于Ruby1.8.7,这就可以了。url_1='http://www.youtube.com/watch?v=8WVTOUh53QY&feature=feedf'url