OpenCV实现平均背景法

 更新时间:2020年03月21日 07:12:35   作者:thystar  
这篇文章主要为大家详细介绍了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;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 深入理解C++11:探索lambda函数的奥秘

    深入理解C++11:探索lambda函数的奥秘

    聚焦于C++11,让我们一起探索lambda函数的奥秘,本指南将带您深入了解这个强大的编程工具,让您在编程世界中如虎添翼,无论您是初学者还是有经验的开发者,本指南都将为您带来全新的视角和实用的技巧,需要的朋友可以参考下
    2024-01-01
  • C语言预处理器使用方法讲解

    C语言预处理器使用方法讲解

    C预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。我们将把C预处理器(C Preprocessor)简写为CPP
    2022-12-12
  • C++中的运算符重载详解

    C++中的运算符重载详解

    大家好,本篇文章主要讲的是C++中的运算符重载详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • C++教程之array数组使用示例详解

    C++教程之array数组使用示例详解

    这篇文章主要为大家介绍了C++教程之array数组使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • C++ Array容器的显示和隐式实例化详细介绍

    C++ Array容器的显示和隐式实例化详细介绍

    这篇文章主要介绍了C++中Array容器的隐式实例化和显式实例化,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-10-10
  • C++11非受限联合体的使用

    C++11非受限联合体的使用

    本文主要介绍了C++11非受限联合体的使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Qt显示QImage图像在label上,并保持自适应大小问题

    Qt显示QImage图像在label上,并保持自适应大小问题

    这篇文章主要介绍了Qt显示QImage图像在label上,并保持自适应大小问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • C++实现LeetCode(205.同构字符串)

    C++实现LeetCode(205.同构字符串)

    这篇文章主要介绍了C++实现LeetCode(205.同构字符串),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++ Boost Bind库示例分析使用

    C++ Boost Bind库示例分析使用

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • C语言实现BST二叉排序树的基本操作

    C语言实现BST二叉排序树的基本操作

    这篇文章主要为大家详细介绍了C语言实现BST二叉排序树的基本操作,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09

最新评论