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


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
安装方法可以通过以下步骤进行: 1. 首先,你可以尝试从清华大学的镜像站点下载opencv-python和opencv-contrib-python。你可以使用以下链接进行下载:opencv-python https://pypi.tuna.tsinghua.edu.cn/simple/opencv-python/ opencv-python-contrib https://pypi.tuna.tsinghua.edu.cn/simple/opencv-contrib-python/ \[1\] 2. 如果以上方法不可行,你可以访问UCI的网站,找到OpenCV模块,并根据你的Python版本和CPU位数选择相应的安装包进行下载。例如,如果你的Python版本是3.9,CPU是64位,你可以选择下载opencv_python-4.5.5-cp39-cp39-win_amd64.whl文件。下载完成后,将该压缩包剪切到你的Scripts文件夹中。然后,在命令提示符中进入Python安装路径的Scripts文件夹,并使用pip命令进行安装。例如,在Python安装路径的Scripts下输入以下命令:pip3.9.exe install D:\python\Scripts\opencv_python-4.5.5-cp39-cp39-win_amd64.whl \[2\] 3. 安装完成后,你可以使用import cv2和import numpy等语句导入opencv和numpy库,并使用相应的函数进行图像处理。例如,你可以使用cv2.imread函数读取图像,并使用img.shape打印图像的形状。\[3\] #### 引用[.reference_title] - *1* *3* [python 38 安装 opencv-python 4.5.5和opencv-python-contrib 4.5.5.62](https://blog.csdn.net/weixin_42888638/article/details/123289881)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [最新openCV-Python安装教程(python:3.9||opencv-python:4.5.5)](https://blog.csdn.net/weixin_43349916/article/details/123232335)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值