OpenCV實現(xiàn)幀間差分法詳解
本文實例為大家分享了OpenCV實現(xiàn)幀間差分法的具體方法,供大家參考,具體內(nèi)容如下
一.基本概念
基于視頻的車輛檢測算法種類很多:光流法檢測,幀差法,背景消除法(其中包括:直方圖法,平均值法,單分布和混合高斯分布背景模型,Kalman濾波等),邊緣檢測法,運動矢量檢測法...下面分享的是運動目標(biāo)檢測算法中最基本的方法—幀間差分法。
相鄰幀間圖像差分思想:檢測出了相鄰兩幀圖像中發(fā)生變化的區(qū)域。該方法是用圖像序列中的連續(xù)兩幀圖像進(jìn)行差分,然后二值化該灰度差分圖像來提取運動信息。由幀間變化區(qū)域檢測分割得到的圖像,區(qū)分出背景區(qū)域和運動車輛區(qū)域,進(jìn)而提取要檢測的車輛目標(biāo)。
它是通過比較圖像序列中前后兩幀圖像對應(yīng)像素點灰度值的不同,通過兩幀相減,如果灰度值很小,可以認(rèn)為該點無運動物體經(jīng)過;反之灰度變化很大,則認(rèn)為有物體經(jīng)過。第k幀和k+1幀圖像fk(x,y),fk+l(x,y)之間的變化用一個二值差分圖像D(x,y)表示,如式:

二值圖中0對應(yīng)前后未變化的地方,1對應(yīng)變化的地方。流程圖如下圖所示:

幀差法的特點是實現(xiàn)簡單,運算速度快,對于動態(tài)環(huán)境自適應(yīng)性是很強(qiáng)的,對光線的變化不是十分的敏感。但是在運動體內(nèi)易產(chǎn)生空洞.特別是目標(biāo)運動速度較快時,影響目標(biāo)區(qū)域準(zhǔn)確提取。我們以年輛檢測為例,車輛檢測除了要檢測出運動車輛.同時還要檢測出暫時停止的車輛,在這個方面,此類方法無能為力。而且如果車輛的體積較大,那么車輛在前后幀中根容易產(chǎn)生重疊部分,尤其是大貨車,這使得幀問差分的結(jié)果主要為車頭和車尾。車輛中間部分的差分值相對報?。纬煽斩?,不利于檢測。
二.程序源代碼
#include "stdafx.h"
#include "highgui.h"
#include "cxcore.h"
#include "ml.h"
#include "cv.h"
void main()
{
CvCapture* capture;
capture=cvCaptureFromFile("video.avi");//獲取視頻
cvNamedWindow("camera",CV_WINDOW_AUTOSIZE);
cvNamedWindow("moving area",CV_WINDOW_AUTOSIZE);
IplImage* tempFrame;//用于遍歷capture中的幀,通道數(shù)為3,需要轉(zhuǎn)化為單通道才可以處理
IplImage* currentFrame;//當(dāng)前幀
IplImage* previousFrame;//上一幀
/*
CvMat結(jié)構(gòu),本質(zhì)上和IplImage差不多,但是因為IplImage里的數(shù)據(jù)只能用uchar的形式存放,當(dāng)需要這些圖像數(shù)據(jù)看作數(shù)據(jù)矩陣來運算時,0~255的精度顯然滿足不了要求;
然而CvMat里卻可以存放任意通道數(shù)、任意格式的數(shù)據(jù)
*/
CvMat* tempFrameMat;
CvMat* currentFrameMat; //IplImage要轉(zhuǎn)成CvMat進(jìn)行處理
CvMat* previousFrameMat;
int frameNum=0;
while(tempFrame=cvQueryFrame(capture))
{
//tempFrame=cvQueryFrame(capture);
frameNum++;
if(frameNum==1)
{
//第一幀先初始化各個結(jié)構(gòu),為它們分配空間
previousFrame=cvCreateImage(cvSize(tempFrame->width,tempFrame->height),IPL_DEPTH_8U,1);
currentFrame=cvCreateImage(cvSize(tempFrame->width,tempFrame->height),IPL_DEPTH_8U,1);
currentFrameMat=cvCreateMat(tempFrame->height, tempFrame->width, CV_32FC1);
previousFrameMat=cvCreateMat(tempFrame->height, tempFrame->width, CV_32FC1);
tempFrameMat=cvCreateMat(tempFrame->height, tempFrame->width, CV_32FC1);
//此時這些IplImage和CvMat都是空的,沒有存有數(shù)據(jù)
}
if(frameNum>=2)
{
cvCvtColor(tempFrame, currentFrame, CV_BGR2GRAY);//轉(zhuǎn)化為單通道灰度圖,此時currentFrame已經(jīng)存了tempFrame的內(nèi)容
/*
用cvConvert將IplImage轉(zhuǎn)為CvMat,接下來用cvAbsDiff對它們處理
經(jīng)過轉(zhuǎn)換后,currentFrame沒有改變,但是tempFrameMat已經(jīng)存了currentFrame的內(nèi)容
*/
cvConvert(currentFrame,tempFrameMat);
cvConvert(previousFrame,previousFrameMat);
cvAbsDiff(tempFrameMat,previousFrameMat,currentFrameMat);//做差求絕對值
/*
在currentFrameMat中找大于20(閾值)的像素點,把currentFrame中對應(yīng)的點設(shè)為255
此處閾值可以幫助把車輛的陰影消除掉
*/
cvThreshold(currentFrameMat,currentFrame,20,255.0,CV_THRESH_BINARY);
//cvConvert(currentFrameMat,currentFrame); //觀察不二值化的情況
cvDilate(currentFrame,currentFrame); //膨脹
cvErode(currentFrame,currentFrame); //腐蝕
cvFlip(currentFrame, NULL, 0); //垂直翻轉(zhuǎn)
//顯示圖像
cvShowImage("camera",tempFrame);
cvShowImage("moving area",currentFrame);
}
//把當(dāng)前幀保存作為下一次處理的前一幀
cvCvtColor(tempFrame, previousFrame, CV_BGR2GRAY);
cvWaitKey(33);
}//end while
//釋放資源
cvReleaseImage(&tempFrame);
cvReleaseImage(&previousFrame);
cvReleaseImage(¤tFrame);
cvReleaseCapture(&capture);
cvReleaseMat(&previousFrameMat);
cvReleaseMat(¤tFrameMat);
cvDestroyWindow("camera");
cvDestroyWindow("moving area");
}
【注意】代碼復(fù)制他處,略有改動,進(jìn)行視頻輸出矯正(源代碼昰倒的圖像)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言一個函數(shù)如何實現(xiàn)好幾個return返回值
本文主要介紹了C語言一個函數(shù)如何實現(xiàn)好幾個return返回值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
C++語言數(shù)據(jù)結(jié)構(gòu) 串的基本操作實例代碼
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu) 串的基本操作實例代碼的相關(guān)資料,需要的朋友可以參考下2017-04-04
深入理解C++中的new/delete和malloc/free動態(tài)內(nèi)存管理及區(qū)別介紹
這篇文章主要介紹了深入理解C++中的new/delete和malloc/free動態(tài)內(nèi)存管理,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09
Ubuntu配置sublime text 3的c編譯環(huán)境的具體步驟
下面小編就為大家?guī)硪黄猆buntu配置sublime text 3的c編譯環(huán)境的具體步驟。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03
C++靜態(tài)成員函數(shù)不能調(diào)用非靜態(tài)成員變量(詳解)
下面小編就為大家?guī)硪黄狢++靜態(tài)成員函數(shù)不能調(diào)用非靜態(tài)成員變量(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12

