1. 程式人生 > 程式設計 >OpenCV實現幀間差分法詳解

OpenCV實現幀間差分法詳解

本文例項為大家分享了OpenCV實現幀間差分法的具體方法,供大家參考,具體內容如下

一.基本概念

基於視訊的車輛檢測演算法種類很多:光流法檢測,幀差法,背景消除法(其中包括:直方圖法,平均值法,單分佈和混合高斯分佈背景模型,Kalman濾波等),邊緣檢測法,運動向量檢測法...下面分享的是運動目標檢測演算法中最基本的方法—幀間差分法。

相鄰幀間影象差分思想:檢測出了相鄰兩幀影象中發生變化的區域。該方法是用影象序列中的連續兩幀影象進行差分,然後二值化該灰度差分影象來提取運動資訊。由幀間變化區域檢測分割得到的影象,區分出背景區域和運動車輛區域,進而提取要檢測的車輛目標。

它是通過比較影象序列中前後兩幀影象對應畫素點灰度值的不同,通過兩幀相減,如果灰度值很小,可以認為該點無運動物體經過;反之灰度變化很大,則認為有物體經過。第k幀和k+1幀影象fk(x,y),fk+l(x,y)之間的變化用一個二值差分影象D(x,y)表示,如式:

OpenCV實現幀間差分法詳解

二值圖中0對應前後未變化的地方,1對應變化的地方。流程圖如下圖所示:

OpenCV實現幀間差分法詳解

幀差法的特點是實現簡單,運算速度快,對於動態環境自適應性是很強的,對光線的變化不是十分的敏感。但是在運動體內易產生空洞.特別是目標運動速度較快時,影響目標區域準確提取。我們以年輛檢測為例,車輛檢測除了要檢測出運動車輛.同時還要檢測出暫時停止的車輛,在這個方面,此類方法無能為力。而且如果車輛的體積較大,那麼車輛在前後幀中根容易產生重疊部分,尤其是大貨車,這使得幀問差分的結果主要為車頭和車尾。車輛中間部分的差分值相對報小.形成空洞,不利於檢測。

二.程式原始碼

#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中的幀,通道數為3,需要轉化為單通道才可以處理
 IplImage* currentFrame;//當前幀
 IplImage* previousFrame;//上一幀
 /*
 CvMat結構,本質上和IplImage差不多,但是因為IplImage裡的資料只能用uchar的形式存放,當需要這些影象資料看作資料矩陣來運算時,0~255的精度顯然滿足不了要求;
然而CvMat裡卻可以存放任意通道數、任意格式的資料
 */
 CvMat* tempFrameMat;
 CvMat* currentFrameMat; //IplImage要轉成CvMat進行處理
 CvMat* previousFrameMat;
 
 int frameNum=0;
 while(tempFrame=cvQueryFrame(capture))
 {
 //tempFrame=cvQueryFrame(capture);
 frameNum++;
 if(frameNum==1)
 {
 //第一幀先初始化各個結構,為它們分配空間
 previousFrame=cvCreateImage(cvSize(tempFrame->width,tempFrame->height),IPL_DEPTH_8U,1);
 currentFrame=cvCreateImage(cvSize(tempFrame->width,1);
 currentFrameMat=cvCreateMat(tempFrame->height,tempFrame->width,CV_32FC1);
 previousFrameMat=cvCreateMat(tempFrame->height,CV_32FC1);
 tempFrameMat=cvCreateMat(tempFrame->height,CV_32FC1);
 //此時這些IplImage和CvMat都是空的,沒有存有資料
 }
 if(frameNum>=2)
 {
 cvCvtColor(tempFrame,currentFrame,CV_BGR2GRAY);//轉化為單通道灰度圖,此時currentFrame已經存了tempFrame的內容
 /*
 用cvConvert將IplImage轉為CvMat,接下來用cvAbsDiff對它們處理
 經過轉換後,currentFrame沒有改變,但是tempFrameMat已經存了currentFrame的內容
 */
 cvConvert(currentFrame,tempFrameMat);
 cvConvert(previousFrame,previousFrameMat);
 
 cvAbsDiff(tempFrameMat,previousFrameMat,currentFrameMat);//做差求絕對值
 /*
 在currentFrameMat中找大於20(閾值)的畫素點,把currentFrame中對應的點設為255
 此處閾值可以幫助把車輛的陰影消除掉
 */
 cvThreshold(currentFrameMat,20,255.0,CV_THRESH_BINARY);
  //cvConvert(currentFrameMat,currentFrame); //觀察不二值化的情況
 
 cvDilate(currentFrame,currentFrame); //膨脹
 cvErode(currentFrame,currentFrame); //腐蝕
 cvFlip(currentFrame,NULL,0); //垂直翻轉
 //顯示影象
 cvShowImage("camera",tempFrame);
 cvShowImage("moving area",currentFrame);
 }
 //把當前幀儲存作為下一次處理的前一幀
 cvCvtColor(tempFrame,previousFrame,CV_BGR2GRAY);
 cvWaitKey(33);
 
 }//end while
 
 //釋放資源
 cvReleaseImage(&tempFrame);
 cvReleaseImage(&previousFrame);
 cvReleaseImage(&currentFrame);
 
 cvReleaseCapture(&capture);
 cvReleaseMat(&previousFrameMat);
 cvReleaseMat(&currentFrameMat);
 cvDestroyWindow("camera");
 cvDestroyWindow("moving area");
}

【注意】程式碼複製他處,略有改動,進行視訊輸出矯正(原始碼昰倒的影象)。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。