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;
}

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

(0)

相关推荐

  • opencv利用视频的前n帧求平均图像

    本文实例为大家分享了opencv利用视频的前n帧求平均图像的具体代码,供大家参考,具体内容如下 自己写的哈,可以用该小程序对视频求解平均模型. //OpenCV中如何累加多幅图像并取平均值 #include "cv.h" #include "highgui.h" int main(int argc,char *argv[]) { int nframe = 50;//利用前nfram帧求解平均图 CvCapture *capture = cvCreateFileCap

  • OpenCV实现平均背景法

    平均背景法的基本思想是计算每个像素的平均值和标准差作为它的背景模型. 平均背景法使用四个OpenCV函数: cvAcc(),累积图像: cvAbsDiff() ,计算一定时间内的每帧图像只差: cvInRange(), 将图像分割成前景区域和背景区域: cvOr(), 将不同的彩色通道图像中合成为一个掩膜图像 代码: /* 平均背景法 */ #include "highgui.h" #include "cv.h" #include<stdlib.h> #

  • opencv平均背景法详解

    本文实例为大家分享了opencv平均背景法的具体代码,供大家参考,具体内容如下 #include<opencv2/opencv.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; IplImage *IavgF, *IdiffF, *IprevF, *IhiF, *IlowF; I

  • C++ OpenCV单峰三角阈值法Thresh_Unimodal详解

    目录 需求说明 具体流程 功能函数 C++测试代码 测试效果 需求说明 在对图像进行处理时,经常会有这类需求:想通过阈值对图像进行二值化分割,以提取自己感兴趣的区域,常见的阈值分割方法有常数分割.最大类间方差法.双峰分割.三角法等等,不同的场景应用不同的阈值方法. 今天要讲的方法,适合当图像的直方图具有明显单峰特征时使用,结合了三角法的原理而设计,相比较OpenCV自带的三角法,好处是可以根据自身需求合理修改函数:如果用OpenCV库的函数,只有一个接口,若不能达到较理想的应用效果,就束手无策了

  • Java OpenCV图像处理之背景切换

    目录 实现步骤 函数详解 示例代码 效果图 实现步骤 1 读取原图片 2 获取原图片的mask 3 获取原图片需要获取的ROI 4 获取新背景的mask 5 融合 3,5 函数详解 示例代码 package com.xu.opencv; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.Scalar; import org.opencv.highgui.HighGui; import o

  • Java OpenCV图像处理之背景消除

    目录 实现步骤 主要代码 效果图 实现步骤 1.获取视频 2.设置形态学结构 3.创建Video.createBackgroundSubtractorMOG2() 4.提取模型 BS 5.进行形态学变换 6.展示结果 主要代码 package com.xu.opencv; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; import ja

  • OpenCV实现图像背景虚化效果原理详解

    目录 0 写在前面 1 小孔成像 2 光学成像 3 虚化效果 4 代码实战 0 写在前面 相信用过相机的同学都知道虚化特效,这是一种使焦点聚集在拍摄主题上,让背景变得朦胧的效果,例如本文最后实现的背景虚化效果 相机虚化特效背后的原理是什么?和计算机视觉有什么关系?本文带你研究这些问题. 1 小孔成像 小学我们就知道,没有光就不存在图像,为了产生图像,场景必须有一个或多个.直接或间接的光源. 如图所示,光照主要分为三类: 散射 直接光照 漫反射 在获得光源后,将产生从物体到检测平面的光线. 由于从

  • Qt+OpenCV利用帧差法实现车辆识别

    目录 一.目标 二.使用Qt界面 三.代码实现 一.目标 Qt界面实现 点击 线程启动按钮播放视频 左边界面显示原视频 右边界面显示车辆识别视频 结果展示如下: 初始界面 点击线程启动后,即可车辆识别 二.使用Qt界面 设计好界面后最好先保存 对按钮设置槽函数 三.代码实现 难点在于:线程同步问题 需要使用到connect函数中的第五个参数[第五个参数 具体说明如下] 1 AutoConnection 为默认参数,由发送信号决定,如果发送信号和接受信号是同一个线程,则调用DirectConnec

  • OpenCV实现去除背景识别的方法总结

    目录 实现效果 实现代码 补充 实现效果 效果如图,只识别一定距离内的物体 哈哈哈哈哈哈哈哈哈,但我不知道这有什么用 实现代码 import pyrealsense2 as rs import numpy as np import cv2 # 排除背景色 WIDTH = 848 HEIGHT = 480 # 初始化 config = rs.config() config.enable_stream(rs.stream.color, WIDTH, HEIGHT, rs.format.bgr8, 3

  • Opencv实现抠图背景图替换功能

    本文实例为大家分享了Opencv实现抠图替换背景图的具体代码,供大家参考,具体内容如下 下面简单图片演示一下: 提取mask: ===> 替换背景:  + = python的opencv代码如下: # coding=utf-8 import cv2 import numpy as np img=cv2.imread('lp.jpg') img_back=cv2.imread('back.jpg') #日常缩放 rows,cols,channels = img_back.shape img_bac

  • OpenCV实现帧差法检测运动目标

    今天的目标是用OpenCV实现对运动目标的检测,这里选用三帧帧差法.代码如下: #include <opencv2/opencv.hpp> #include <cv.h> #include <highgui.h> #include <stdio.h> #include <ctype.h> double Threshold_index=0; const int CONTOUR_MAX_AERA = 200; void trackbar(int po

随机推荐