遗留物检测算法及实现

简介:         从最终实现的角度来看,说不上是遗留物检测,至多是静止目标检测【运动物体长时间滞留检测】。实验室同学搞毕业设计,帮忙弄弄,也没弄成。          本文将分别给出老外论文+对应的代码【在老外论文基础上改进的】和国内的论文+代码【失败,能力不行】。

        从最终实现的角度来看,说不上是遗留物检测,至多是静止目标检测【运动物体长时间滞留检测】。实验室同学搞毕业设计,帮忙弄弄,也没弄成。

         本文将分别给出老外论文+对应的代码【在老外论文基础上改进的】和国内的论文+代码【失败,能力不行】。总体思路都是帧间差分法,没有用sift特征匹配或者在线学习。

算法一:

《An abandoned object detection system based on dual backgroundsegmentation》 IEEE 2009

搞了两个背景缓冲区:

Current_background:初始为第一帧,其后对每个像素,若下一帧像素大于该背景像素,则该出背景像素加1,否则该处背景像素减1。【挺神奇的,好处是This way, even if the foreground ischanging at a fast pace, it will not affect the background but if theforeground is stationary, it gradually merges into the background.但是效果还是不及混合高斯,因为适应期太长太频繁了】

 Buffer_background:论文上说每隔20秒更新一次,直接拷贝Current_background,遗留物检测直接通过Current_background和Buffer_background相减即可。【他这边认为一个遗留物丢弃满20秒,如果还在,则认为该遗留物为背景了】。随后,搞了一堆跟踪该区域的东西,我不太感兴趣。

 本文对上述的改进的目标是物体如果被遗弃了,那么它就应该一直被检测到。我额外搞了一个遗弃背景模版abandon_background,用于记录遗弃物之前的背景图像。

A.若物体离开,则abandon相应区域恢复到当前current的值,buffer更新为当前整个current。B.若物体未离开,则用abandon对buffer局部更新


整体算法:

1.      第一帧,用来初始化Current_background和Buffer_background

2.      通过两个背景区域计算遗留物

3.      每一帧更新Current_background

4.      若时间间隔满足,更新Buffer_background和遗弃物背景abandon_background,更新计数器

   a.      若遗弃物背景首次更新,根据current和buffer之差,在相应的地方赋current的值,其余为0

   b.      进行物体离开判断,即:若abandon与current对应区域背景像素不同,则物体还未离开,否则离开

   c.      若物体离开,将current更新abandon的相应区域,buffer复制完整的current

   d.      若物体未离开,将abandon更新buffer的相应区域,abandon保持不变。

5.      读取下一帧,返回2


代码:

调用的函数:

#include "Model.h"
#define Th 50
#define Ta 90

int first_update = 0;//首次更新标志

void calc_fore(IplImage *current,IplImage *back,IplImage *fore)
{
	int i,j;

	for (i=0;i<current->height;i++)
	{
		for (j=0;j<current->width;j++)
		{
			if (abs((u_char)current->imageData[i*current->widthStep+j] - (u_char)back->imageData[i*current->widthStep+j]) <=Ta )
			{
				fore->imageData[i*current->widthStep+j] = 0;//background
			}else
			{
				fore->imageData[i*current->widthStep+j] = 255;//foreground
			}
		}
	}
}

void update_currentback(IplImage *current,IplImage *curr_back)
{
	int i,j;
	int p,q;

	for (i=0;i<current->height;i++)
	{
		for (j=0;j<current->width;j++)
		{
			p = (u_char)current->imageData[i * current->widthStep + j];
			q = (u_char)curr_back->imageData[i * current->widthStep + j];
			//printf("%d,%d\n",p,q);

			if (p >= q)
			{
				if (q == 255)
				{
					q = 254;
				}
				curr_back->imageData[i * current->widthStep + j] = q + 1;
			}else
			{
				if (q == 0)
				{
					q = 1;
				}
				curr_back->imageData[i * current->widthStep + j] = q - 1;
			}
		}
	}
}

void update_bufferedback(IplImage *curr_back,IplImage *buf_back,IplImage *abandon)
{
	int i,j,height,width;
	int leave_flag = 0;
	
	height = curr_back->height;
	width = curr_back->widthStep;

	if (first_update == 0)
	{
		for ( i = 0;i < height; i++)
		{
			for (j = 0;j < width; j++)
			{
				if (abs((u_char)curr_back->imageData[i*width+j] - (u_char)buf_back->imageData[i*width+j]) <=Th )
				{
					abandon->imageData[i*width+j] = 0;//background
				}else
				{
					abandon->imageData[i*width+j] = curr_back->imageData[i*width+j];//foreground
					first_update = 1;
				}
			}
		}
		return;
	}

	//物体离开判断
	for ( i = 0;i < height; i++)
	{
		for (j = 0;j < width; j++)
		{
			if (abandon->imageData[i*width+j] != 0)
			{
				if (abandon->imageData[i*width+j] != curr_back->imageData[i*width+j])
				{
					leave_flag = 1;					//物体掩膜处之前背景与当前的不一致,1:物体未离开,0:物体离开
				}
			}
		}
	}
	
	if(leave_flag == 0)		//物体离开
	{
		cvCopy(curr_back,buf_back);
		for ( i = 0;i < height; i++)
		{
			for (j = 0;j < width; j++)
			{
				if (abandon->imageData[i*width+j] != 0)
				{
					abandon->imageData[i*width+j] = curr_back->imageData[i*width+j];
				}
			}
		}
	}else
	{
		for ( i = 0;i < height; i++)
		{
			for (j = 0;j < width; j++)
			{
				if (abandon->imageData[i*width+j] != 0)
				{
					buf_back->imageData[i*width+j] = abandon->imageData[i*width+j];
				}
			}
		}
	}
	

}

主函数:

// abandon_left.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "Model.h"

int _tmain(int argc, _TCHAR* argv[])
{
	CvCapture *capture=cvCreateFileCapture("test.avi");
	IplImage *current_back,*buff_back,*abandon,*frame,*current_img,*fore;
	int count,intern;

	frame = cvQueryFrame(capture);
	fore = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	current_back = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	current_img = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	buff_back = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	abandon = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);

	count=0;
	intern = count + 20;
	
	while (1)
	{
		cvCvtColor(frame,current_img,CV_RGB2GRAY);

		if (count == 0)
		{
			//初始化背景模版
			cvCopy(current_img,current_back);
			cvCopy(current_img,buff_back);
		}

		if (count > 0)
		{
			//计算前景掩膜
			calc_fore(current_back,buff_back,fore);

			//更新跟踪背景
			update_currentback(current_img,current_back);

			if (count == intern)
			{
				update_bufferedback(current_back,buff_back,abandon);
				intern = count + 20;
			}
			cvShowImage("current",current_img);
			cvShowImage("current_back",current_back);
			cvShowImage("buff_back",buff_back);
			cvShowImage("abandon detection",fore);
		}

		count++;
		frame =cvQueryFrame(capture);

		if (cvWaitKey(23)>=0)
		{
			break;
		}
	}
	cvNamedWindow("current",0);
	cvNamedWindow("buff_back",0);
	cvNamedWindow("current_back",0);
	cvNamedWindow("abandon detection",0);
	cvReleaseCapture(&capture);
	return 0;
}

效果图:




说明:左下角有个女的运动规律也符合静止目标检测规律,所以也被检测出来了。后期可以通过外接矩形长宽比等其他手段过滤掉。

视频+代码工程的下载连接:http://download.csdn.net/detail/jinshengtao/7157943


算法二:

《一种基于双背景模型的遗留物检测方法》

搞了个脏背景和纯背景,定义:

当视频场景中不出现运动目标,或者背景不受场景中所出现的运动目标影响时,这样的背景称为纯背景。否则,称为脏背景

它们的更新规则:

一般背景的更新按照帧间差分法:


脏背景使用全局更新,直接赋值一般背景:


纯背景根据前景掩膜,进行局部更新,即若前景掩膜被标记为运动的部分,则相应的纯背景区域用上一帧的纯背景更新;若前景掩膜被标记为非运动的部分,则相应的纯背景区域用当前帧的一般背景更新。


静止目标前景检测算法可以通过以下公式看明白:


具体算法流程不给咯,论文没提,自己摸索的,反正试验效果失败了。

代码:

// left_bag.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#define u_char unsigned char
#define alfa 0.03
#define Th 60
#define Ta 60
#define Tb 40

void calc_fore(IplImage *current,IplImage *back,IplImage *fore)
{
	int i,j;

	for (i=0;i<current->height;i++)
	{
		for (j=0;j<current->width;j++)
		{
			if (abs((u_char)current->imageData[i*current->widthStep+j] - (u_char)back->imageData[i*current->widthStep+j]) <=Th )
			{
				fore->imageData[i*current->widthStep+j] = 0;//background
			}else
			{
				fore->imageData[i*current->widthStep+j] = 255;//foreground
			}
		}
	}
}

void update_back(IplImage *current,IplImage *back,IplImage *B_p,IplImage *B_d,IplImage *fore,IplImage *B_p_pre)
{
	int i,j;

	//更新B_n
	for (i=0;i<current->height;i++)
	{
		for (j=0;j<current->width;j++)
		{
			back->imageData[i*current->widthStep+j] = (1-alfa)*current->imageData[i*current->widthStep+j] + alfa * back->imageData[i*current->widthStep+j];		
		}
	}

	//更新B_d
	cvCopy(back,B_d);
	
	//更新B_p
	for (i = 0;i < fore->height;i++)
	{
		for (j = 0;j < fore->width;j++)
		{
			if ((unsigned char)fore->imageData[i*fore->widthStep + j ] == 255)
			{
				B_p->imageData[i*fore->widthStep + j] = B_p_pre->imageData[i*fore->widthStep + j];
			}else
			{
				B_p->imageData[i*fore->widthStep + j] = back->imageData[i*fore->widthStep + j];
			}
		}
	}
}

void calc_StaticTarget(IplImage *current,IplImage *B_d,IplImage *B_p,IplImage *M_s,IplImage *M_m,IplImage *M_f)
{
	int i,j;

	for (i = 0;i < current->height;i++)
	{
		for (j = 0;j < current->width;j++)
		{
			if (abs((u_char)current->imageData[i*current->widthStep+j] - (u_char)B_d->imageData[i*current->widthStep+j]) <= Th )
			{
				M_s->imageData[i*current->widthStep+j] = 255;
			}else
			{
				M_s->imageData[i*current->widthStep+j] = 0;
			}

			if (abs((u_char)B_p->imageData[i*current->widthStep+j] - (u_char)B_d->imageData[i*current->widthStep+j]) > Tb)
			{
				M_m->imageData[i*current->widthStep+j] = 255;
			}else
			{
				M_m->imageData[i*current->widthStep+j] = 0;
			}

			if (((unsigned char)M_m->imageData[i*current->widthStep+j] == 255) &&((unsigned char)M_s->imageData[i*current->widthStep+j] == 255))
			{
				M_f->imageData[i*current->widthStep+j] = 255;
			}else
			{
				M_f->imageData[i*current->widthStep+j] = 0;
			}
		}
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	CvCapture *capture=cvCreateFileCapture("test.avi");
	IplImage *frame,*current_img,*B_n,*B_p,*B_d,*B_p_pre;
	IplImage *M,*M1,*M_s,*M_m,*M_f;
	int count,i,j;

	frame = cvQueryFrame(capture);
	current_img = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	B_n = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	B_p = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	B_d = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	B_p_pre = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);

	M = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	M1 = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	M_s = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	M_m = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);
	M_f = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,1);

	count=0;
	while (1)
	{
		cvCvtColor(frame,current_img,CV_RGB2GRAY);

		if (count == 0)
		{
			//初始化各种背景模版
			cvCopy(current_img,B_n);
			cvCopy(current_img,B_p);
			cvCopy(current_img,B_d);
			cvCopy(current_img,B_p_pre);
		}

		if (count > 1)
		{
			//计算前景掩膜
			calc_fore(current_img,B_n,M1);

			//膨胀腐蚀操作
			cvDilate(M1, M, 0, 1);
			cvErode(M, M1, 0, 2);
			cvDilate(M1, M, 0,1);	

			//静止目标检测
			calc_StaticTarget(current_img,B_d,B_p,M_s,M_m,M_f);

			//更新跟踪背景
			update_back(current_img,B_n,B_p,B_d,M,B_p_pre);

			cvShowImage("pure ground",B_p);
			cvShowImage("dirty ground",B_d);
			cvShowImage("static target",M_f);
			cvShowImage("fore ground",M);
			cvCopy(B_p,B_p_pre);
		}

		count++;
		frame =cvQueryFrame(capture);
		

		if (cvWaitKey(23)>=0)
		{
			break;
		}
	}
	cvNamedWindow("pure ground",0);
	cvNamedWindow("dirty ground",0);
	cvNamedWindow("static target",0);
	cvNamedWindow("fore ground",0);
	cvReleaseCapture(&capture);
	return 0;
}

算法三【MATLAB toolbox中的一个demo】

理论部分没看,在控制台直接输入:edit videoabandonedobj 会有相应的代码跳出来。

在help中搜索Abandoned Object Detection,会有理论部分介绍

视频素材下载地址:http://www.mathworks.cn/products/viprocessing/vipdemos.html

代码:【2010b 版本可跑】

clc;
clear;

status = videogetdemodata('viptrain.avi');
if ~status
    displayEndOfDemoMessage(mfilename);
    return;
end

roi = [80 100 240 360];
% Maximum number of objects to track
maxNumObj = 200;
% Number of frames that an object must remain stationary before an alarm is
% raised
alarmCount = 45;
% Maximum number of frames that an abandoned object can be hidden before it
% is no longer tracked
maxConsecutiveMiss = 4;
% Maximum allowable change in object area in percent
areaChangeFraction = 15;
% Maximum allowable change in object centroid in percent
centroidChangeFraction = 20;
% Minimum ratio between the number of frames in which an object is detected
% and the total number of frames, for that object to be tracked.
minPersistenceRatio = 0.7;
% Offsets for drawing bounding boxes in original input video
PtsOffset = int32(repmat([roi(1); roi(2); 0 ; 0],[1 maxNumObj]));

hVideoSrc = video.MultimediaFileReader;
hVideoSrc.Filename = 'viptrain.avi';
hVideoSrc.VideoOutputDataType = 'single';

hColorConv = video.ColorSpaceConverter;
hColorConv.Conversion = 'RGB to YCbCr';

hAutothreshold = video.Autothresholder;
hAutothreshold.ThresholdScaleFactor = 1.3;

hClosing = video.MorphologicalClose;
hClosing.Neighborhood = strel('square',5);

hBlob = video.BlobAnalysis;
hBlob.MaximumCount = maxNumObj;
hBlob.NumBlobsOutputPort = true;
hBlob.MinimumBlobAreaSource = 'Property';
hBlob.MinimumBlobArea = 100;
hBlob.MaximumBlobAreaSource = 'Property';
hBlob.MaximumBlobArea = 2500;
hBlob.ExcludeBorderBlobs = true;

hDrawRectangles1 = video.ShapeInserter;
hDrawRectangles1.Fill = true;
hDrawRectangles1.FillColor = 'Custom';
hDrawRectangles1.CustomFillColor = [1 0 0];
hDrawRectangles1.Opacity = 0.5;

hDisplayCount = video.TextInserter;
hDisplayCount.Text = '%4d';
hDisplayCount.Color = [1 1 1];

hAbandonedObjects = video.VideoPlayer;
hAbandonedObjects.Name = 'Abandoned Objects';
hAbandonedObjects.Position = [10 300 roi(4)+25 roi(3)+25];

hDrawRectangles2 = video.ShapeInserter;
hDrawRectangles2.BorderColor = 'Custom';
hDrawRectangles2.CustomBorderColor = [0 1 0];

hDrawBBox = video.ShapeInserter;
hDrawBBox.BorderColor = 'Custom';
hDrawBBox.CustomBorderColor = [1 1 0];

hAllObjects = video.VideoPlayer;
hAllObjects.Position = [45+roi(4) 300 roi(4)+25 roi(3)+25];
hAllObjects.Name = 'All Objects';

hDrawRectangles3 = video.ShapeInserter;
hDrawRectangles3.BorderColor = 'Custom';
hDrawRectangles3.CustomBorderColor = [0 1 0];

hThresholdDisplay = video.VideoPlayer;
hThresholdDisplay.Position = ...
            [80+2*roi(4) 300 roi(4)-roi(2)+25 roi(3)-roi(1)+25];
hThresholdDisplay.Name = 'Threshold';

firsttime = true;
while ~isDone(hVideoSrc)
    Im = step(hVideoSrc);

    % Select the region of interest from the original video
    OutIm = Im(roi(1):end, roi(2):end, :);

    YCbCr = step(hColorConv, OutIm);
    CbCr  = complex(YCbCr(:,:,2), YCbCr(:,:,3));

    % Store the first video frame as the background
    if firsttime
        firsttime = false;
        BkgY      = YCbCr(:,:,1);
        BkgCbCr   = CbCr;
    end
    SegY    = step(hAutothreshold, abs(YCbCr(:,:,1)-BkgY));
    SegCbCr = abs(CbCr-BkgCbCr) > 0.05;

    % Fill in small gaps in the detected objects
    Segmented = step(hClosing, SegY | SegCbCr);

    % Perform blob analysis
    [Area, Centroid, BBox, Count] = step(hBlob, Segmented);

    % Call the helper function that tracks the identified objects and
    % returns the bounding boxes and the number of the abandoned objects.
    [OutCount, OutBBox] = videoobjtracker(Area, Centroid, BBox, Count,...
       areaChangeFraction, centroidChangeFraction, maxConsecutiveMiss, ...
       minPersistenceRatio, alarmCount);

    % Display the abandoned object detection results
    Imr = step(hDrawRectangles1, Im, OutBBox+PtsOffset);
    Imr(1:15,1:30,:) = 0;
    Imr = step(hDisplayCount, Imr, OutCount);
    step(hAbandonedObjects, Imr);

    % Display all the detected objects
    Imr = step(hDrawRectangles2, Im, BBox+PtsOffset);
    Imr(1:15,1:30,:) = 0;
    Imr = step(hDisplayCount, Imr, OutCount);
    Imr = step(hDrawBBox, Imr, roi);
    step(hAllObjects, Imr);

    % Display the segmented video
    SegIm = step(hDrawRectangles3, repmat(Segmented,[1 1 3]), BBox);
    step(hThresholdDisplay, SegIm);
end

release(hVideoSrc);

虽然不是自己的研究方向,但也算尝试了吧。马上快答辩咯,攒个人品先~

目录
相关文章
|
26天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于MSER和HOG特征提取的SVM交通标志检测和识别算法matlab仿真
### 算法简介 1. **算法运行效果图预览**:展示算法效果,完整程序运行后无水印。 2. **算法运行软件版本**:Matlab 2017b。 3. **部分核心程序**:完整版代码包含中文注释及操作步骤视频。 4. **算法理论概述**: - **MSER**:用于检测显著区域,提取图像中稳定区域,适用于光照变化下的交通标志检测。 - **HOG特征提取**:通过计算图像小区域的梯度直方图捕捉局部纹理信息,用于物体检测。 - **SVM**:寻找最大化间隔的超平面以分类样本。 整个算法流程图见下图。
|
1月前
|
算法 安全
分别使用OVP-UVP和OFP-UFP算法以及AFD检测算法实现反孤岛检测simulink建模与仿真
本课题通过Simulink建模与仿真,实现OVP-UVP、OFP-UFP算法及AFD检测算法的反孤岛检测。OVP-UVP基于电压幅值变化,OFP-UFP基于频率变化,而AFD则通过注入频率偏移信号来检测孤岛效应,确保电力系统安全稳定运行。系统使用MATLAB 2013b进行建模与仿真验证。
|
4天前
|
存储 JSON 算法
TDengine 检测数据最佳压缩算法工具,助你一键找出最优压缩方案
在使用 TDengine 存储时序数据时,压缩数据以节省磁盘空间是至关重要的。TDengine 支持用户根据自身数据特性灵活指定压缩算法,从而实现更高效的存储。然而,如何选择最合适的压缩算法,才能最大限度地降低存储开销?为了解决这一问题,我们特别推出了一个实用工具,帮助用户快速判断并选择最适合其数据特征的压缩算法。
12 0
|
18天前
|
算法 计算机视觉 Python
圆形检测算法-基于颜色和形状(opencv)
该代码实现了一个圆检测算法,用于识别视频中的红色、白色和蓝色圆形。通过将图像从RGB转换为HSV颜色空间,并设置对应颜色的阈值范围,提取出目标颜色的区域。接着对这些区域进行轮廓提取和面积筛选,使用霍夫圆变换检测圆形,并在原图上绘制检测结果。
43 0
|
3月前
|
机器学习/深度学习 监控 算法
目标检测算法技术
8月更文挑战第11天
|
3月前
|
机器学习/深度学习 监控 算法
目标检测算法
8月更文挑战第5天
|
3月前
|
机器学习/深度学习 监控 算法
目标检测算法
8月更文挑战第8天
|
4月前
|
监控 算法 自动驾驶
目标检测算法:从理论到实践的深度探索
【7月更文第18天】目标检测,作为计算机视觉领域的核心任务之一,旨在识别图像或视频中特定对象的位置及其类别。这一技术在自动驾驶、视频监控、医疗影像分析等多个领域发挥着至关重要的作用。本文将深入浅出地介绍目标检测的基本概念、主流算法,并通过一个实际的代码示例,带您领略YOLOv5这一高效目标检测模型的魅力。
510 11
|
4月前
|
机器学习/深度学习 人工智能 监控
人工智能 - 目标检测算法详解及实战
目标检测需识别目标类别与位置,核心挑战为复杂背景下的多目标精准快速检测。算法分两步:目标提取(滑动窗口或区域提议)和分类(常用CNN)。IoU衡量预测与真实框重叠度,越接近1,检测越准。主流算法包括R-CNN系列(R-CNN, Fast R-CNN, Faster R-CNN),YOLO系列,SSD,各具特色,如Faster R-CNN高效候选区生成与检测,YOLO适用于实时应用。应用场景丰富,如自动驾驶行人车辆检测,安防监控,智能零售商品识别等。实现涉及数据准备、模型训练(示例YOLOv3)、评估(Precision, Recall, mAP)及测试。
129 5
|
4月前
|
机器学习/深度学习 人工智能 算法
计算机视觉:目标检测算法综述
【7月更文挑战第13天】目标检测作为计算机视觉领域的重要研究方向,近年来在深度学习技术的推动下取得了显著进展。然而,面对复杂多变的实际应用场景,仍需不断研究和探索更加高效、鲁棒的目标检测算法。随着技术的不断发展和应用场景的不断拓展,相信目标检测算法将在更多领域发挥重要作用。