OpenCV实现平均背景法
作者:thystar 发布时间:2023-06-28 18:25:41
标签:OpenCV,平均背景法
平均背景法的基本思想是计算每个像素的平均值和标准差作为它的背景模型。
平均背景法使用四个OpenCV函数:
cvAcc(),累积图像;
cvAbsDiff() ,计算一定时间内的每帧图像只差;
cvInRange(), 将图像分割成前景区域和背景区域;
cvOr(), 将不同的彩色通道图像中合成为一个掩膜图像
代码:
/*
平均背景法
*/
#include "highgui.h"
#include "cv.h"
#include<stdlib.h>
#include<stdio.h>
//为不同的临时指针图像和统计属性创建指针
//Float, 3-channel images
IplImage* IavgF, * IdiffF, * IprevF, * IhiF, *IlowF;
IplImage* Iscratch, *Iscratch2;
//Float 1-channel images
IplImage* Igray1, * Igray2, * Igray3;
IplImage* Ilow1, * Ilow2, * Ilow3;
IplImage* Ihi1, *Ihi2, * Ihi3;
//Byte, 1-channel image
IplImage* Imask;
IplImage* Imaskt;
//Counts number of images learned for averaging later.
float Icount;
// 创建一个函数来给需要的所有临时图像分配内存
//为了方便,我们传递一幅图像(来自视频)作为大小参考来分配临时图像
void AllocateImages(IplImage* I)
{
CvSize sz = cvGetSize(I);
IavgF = cvCreateImage(sz, IPL_DEPTH_32F, 3);
IdiffF = cvCreateImage(sz, IPL_DEPTH_32F,3);
IprevF = cvCreateImage(sz, IPL_DEPTH_32F,3);
IhiF = cvCreateImage(sz, IPL_DEPTH_32F, 3);
IlowF = cvCreateImage(sz, IPL_DEPTH_32F,3);
Ilow1 = cvCreateImage(sz, IPL_DEPTH_32F,1);
Ilow2 = cvCreateImage(sz, IPL_DEPTH_32F,1);
Ilow3 = cvCreateImage(sz, IPL_DEPTH_32F,1);
Ihi1 = cvCreateImage(sz, IPL_DEPTH_32F,1);
Ihi2 = cvCreateImage(sz, IPL_DEPTH_32F,1);
Ihi3 = cvCreateImage(sz, IPL_DEPTH_32F,1);
cvZero(IavgF);
cvZero(IdiffF);
cvZero(IprevF);
cvZero(IhiF);
cvZero(IlowF);
Icount = 0.00001;
Iscratch = cvCreateImage(sz, IPL_DEPTH_32F,3);
Iscratch2 = cvCreateImage(sz, IPL_DEPTH_32F,3);
Igray1 = cvCreateImage(sz, IPL_DEPTH_32F,1);
Igray2 = cvCreateImage(sz, IPL_DEPTH_32F,1);
Igray3 = cvCreateImage(sz, IPL_DEPTH_32F,1);
Imask = cvCreateImage(sz, IPL_DEPTH_8U, 1);
Imaskt = cvCreateImage(sz, IPL_DEPTH_8U,1);
cvZero(Iscratch);
cvZero(Iscratch2);
}
//学习累积背景图像和每一帧图像差值的绝对值
// Learn the background statistics for one more frame
// I is a color sample of the background, 3-channel, 8u
void accumulateBackground(IplImage *I)
{
static int first = 1;
cvCvtScale(I, Iscratch, 1, 0);
if(!first)
{
cvAcc(Iscratch,IavgF);
cvAbsDiff(Iscratch, IprevF, Iscratch2);
cvAcc(Iscratch2,IdiffF);
Icount += 1.0;
}
first = 0;
cvCopy(Iscratch, IprevF);
}
//setHighThreshold和setLowThreshold都是基于每一帧图像平均绝对差设置阈值的有效函数
void setHighThreshold(float scale)
{
cvConvertScale(IdiffF, Iscratch, scale);
cvAdd(Iscratch, IavgF, IhiF);
cvSplit(IhiF, Ihi1, Ihi2, Ihi3, 0);
}
void setLowThreshold(float scale)
{
cvConvertScale(IdiffF, Iscratch, scale);
cvSub(IavgF, Iscratch, IlowF);
cvSplit(IlowF, Ilow1, Ilow2, Ilow3, 0);
}
//当积累了足够多的帧图像之后,就将其转化为一个背景的统计模型
//计算每一个像素的均值和方差观测
void createModelsfromStats()
{
cvConvertScale(IavgF, IavgF, (double)(1.0/Icount));
cvConvertScale(IdiffF, IdiffF, (double)(1.0/Icount));
//Make sure diff is always something
cvAddS(IdiffF, cvScalar(1.0, 1.0, 1.0), IdiffF);
setHighThreshold(7.0);
setLowThreshold(6.0);
}
//有了背景模型,同时给出了高,低阈值,就能用它将图像分割为前景和背景
// Create a binary: 0,255 mask where 255 means foregrond pixel
// I Input image, 3-channel, 8u
//Imask
void backgroundDiff(IplImage* I)
{
cvCvtScale(I, Iscratch, 1, 0);
cvSplit(Iscratch, Igray1, Igray2, Igray3, 0);
//Channel 1
cvInRange(Igray1, Ilow1, Ihi1, Imask);
//Channel 2
cvInRange(Igray2, Ilow2, Ihi2, Imaskt);
cvOr(Imask, Imaskt, Imask);
//Channel 3
cvInRange(Igray3, Ilow3, Ihi3, Imaskt);
cvOr(Imask, Imaskt, Imask);
//Finally, invert the result
cvSubRS(Imask, cvScalar(255), Imask);
}
//完成背景建模后, 释放内存
void DeallocateImage()
{
cvReleaseImage(&IavgF);
cvReleaseImage(&IdiffF);
cvReleaseImage(&IprevF);
cvReleaseImage(&IhiF);
cvReleaseImage(&IlowF);
cvReleaseImage(&Ilow1);
cvReleaseImage(&Ilow2);
cvReleaseImage(&Ilow3);
cvReleaseImage(&Iscratch);
cvReleaseImage(&Iscratch2);
cvReleaseImage(&Igray1);
cvReleaseImage(&Igray2);
cvReleaseImage(&Igray3);
cvReleaseImage(&Imaskt);
}
//主函数
int main()
{
CvCapture* capture = cvCreateFileCapture("tree.avi");
if(!capture)
{
return -1;
}
cvNamedWindow("win1");
cvNamedWindow("win2");
IplImage* rawImage = cvQueryFrame(capture);
cvShowImage("win1", rawImage);
AllocateImages(rawImage);
int i = 0;
while(1)
{
if(i <= 30)
{
accumulateBackground(rawImage);
if(i == 30)
{
createModelsfromStats();
}
}
else
{
backgroundDiff(rawImage);
}
cvShowImage("win2", Imask);
if(cvWaitKey(33) == 27)
{
break;
}
if(!(rawImage = cvQueryFrame(capture)))
{
break;
}
cvShowImage("win1", rawImage);
if(i == 56 || i == 63)
cvWaitKey();
i = i+1;
}
DeallocateImage();
return 0;
}
来源:https://blog.csdn.net/thystar/article/details/41279305
0
投稿
猜你喜欢
- 本文实例为大家分享了java实现幸运抽奖功能的具体代码,供大家参考,具体内容如下本系统较为简单,未使用是什么多的算法,也未添加保存文件读取文
- 在Android原生的TextView的基础上,可收缩/扩展的TextView:PhilExpandableTextView。实现原理:核心
- 本文实例讲述了C#实现彻底删除文件的方法。分享给大家供大家参考。具体实现方法如下:经常用360的文件粉碎,删除隐私文件貌似还不错的。不过C#
- 无平台限制,依赖于快递api网接口 ----------------实体类 [DataContract]  
- 前言在我们开发过程中,由于主流的架构都是采用前后端分离的方式,我们作为后端开发者需要为前段持续地提供运行在容器中最新代码,虽然可
- 1.前言APP冷启动比较慢,点击桌面图片需要用户等待很久,体验较差。2.APP启动方式冷启动(Cold start)场景:冷启动是指APP在
- 先看实例 代码如下 classip { privatestaticlongiptolong(stringstrip) //将127.0.0.
- 本文实例讲述了Java线程之守护线程(Daemon)用法。分享给大家供大家参考。具体如下:守护线程(Daemon)Java有两种Thread
- 一、加密方案介绍对接口的加密解密操作主要有下面两种方式:自定义消息转换器优势:仅需实现接口,配置简单。劣势:仅能对同一类型的MediaTyp
- 前言一般生成的PDF文档默认的文档底色为白色,我们可以通过一定方法来更改文档的背景色,以达到文档美化以及保护双眼的作用。 以下内容提供了Ja
- 本文实例讲述了Java类加载器和类加载机制。分享给大家供大家参考,具体如下:一 点睛1 类加载器负责将.class文件(可能在磁盘上,也可能
- 摘要:想必大家做开发的时候都会用到下拉刷新的控件,现在各种第三方的下拉刷新控件不胜枚举。当然最NB的还是XListView。其他也有针对Gr
- 目标&背景我们以“处理订单数据”为例,假设我们的应用是一个分布式应用,有"订单应用","物流应用&qu
- WPF中有一个DrawingContext类,该类提供了很多画法方法,例如DrawLine,DrawText,DrawRectangle等。
- 一、概念:LINQ to Entities - ADO.NET | Microsoft 官方文档EF实体框架目前版本为EF6。EF6 可实现
- Maven Repository仓库的具体使用不知道大家是不是这样,反正我访问官网的时候不是非常慢就是崩溃,所以我就将我用过的Maven依赖
- 前言好记性不如烂笔头,日期时间类那么花哨不如记下来多看两眼。提示:以下是本篇文章正文内容,下面案例可供参考一.日期时间类的包代码如下(示例)
- 发现问题最近在进行压测发现,有一些接口时好时坏,通过sentry日志平台及sky walking平台跟踪发现,用户张三获取到的用户上下文确是
- 双向循环链表定义相比于单链表,有两个指针,next指针指向下一个结点,prior指针指向上一个结点,最后一个结点的next指针指向头结点,头
- 本文实例讲述了C#中异步回调函数用法。分享给大家供大家参考。具体如下:static void Main(string[] args){ Fu