OpenCV实现平均背景法

作者:thystar 时间:2023-06-28 18:25:41 

平均背景法的基本思想是计算每个像素的平均值和标准差作为它的背景模型。

平均背景法使用四个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

标签:OpenCV,平均背景法
0
投稿

猜你喜欢

  • C#中Invoke的用法讲解

    2023-10-26 03:24:36
  • Android基础之隐藏标题栏/设置为全屏/横竖屏切换

    2022-06-22 14:29:35
  • HighCharts图表控件在ASP.NET WebForm中的使用总结(全)

    2022-07-13 02:11:12
  • Android仿美团网、大众点评购买框悬浮效果修改版

    2023-10-05 13:12:17
  • JavaWeb开发基于ssm的校园服务系统(实例详解)

    2022-11-07 16:40:48
  • Android传感器SensorEventListener之加速度传感器

    2023-03-07 15:05:50
  • java开发中使用IDEA活动模板快速增加注释的方法

    2021-09-25 20:42:24
  • Android仿微信朋友圈实现滚动条下拉反弹效果

    2023-02-21 15:48:58
  • WPF调用ffmpeg实现屏幕录制

    2023-04-23 13:57:00
  • Java实现TFIDF算法代码分享

    2023-12-23 20:54:45
  • 使用递归实现数组求和示例分享

    2023-04-24 02:17:40
  • 在实践中了解Java反射机制应用

    2021-06-29 02:40:14
  • 详解C# WinForm如何实现自动更新程序

    2022-03-04 02:19:29
  • spring cloud gateway跨域全局CORS配置方式

    2021-11-02 01:09:00
  • Android开发实现模仿微信小窗口功能【Dialog对话框风格窗口】

    2022-01-27 10:11:01
  • Android基础总结篇之三:Activity的task相关介绍

    2023-06-15 14:47:17
  • C#实现创建标签PDF文件的示例代码

    2023-09-15 07:04:58
  • Android之日期时间选择控件DatePicker和TimePicker实例

    2023-08-02 14:57:26
  • java实现计算器功能

    2022-10-28 06:52:09
  • 微信小程序与AspNetCore SignalR聊天实例代码

    2022-12-21 01:29:06
  • asp之家 软件编程 m.aspxhome.com