OpenCV運動目標檢測
下面介紹如何運用openCV中的函式cvUpdateMotionHistory進行運動目標檢測。cvUpdateMotionHistory的功能是更新運動歷史影象,它的原型是:
void cvUpdateMotionHistory(
const CvArr* silhouette,
CvArr* mhi,
double timestamp,
double duration );
各個引數解釋如下,
silhouette,由幀間差分得到的運動輪廓影象。
mhi,motion histoty image的縮寫,表示運動歷史影象。
timestamp,時間標記。
duration,發生過運動的畫素所能保持的最長時間。
作為輸出的運動歷史影象mhi的與作為輸入的運動輪廓影象silhouette的具體關係可以表達為如下三種情況:
(1)mhi(x,y) = timestamp if silhouette(x,y)!=0.即當運動輪廓影象在座標(x,y)處不為零時,那麼將mhi在(x,y)處打上時間標記timestamp.
(2)mhi(x,y) = 0 if silhouette(x, y) = 0 and mhi(x,y) < (timestamp - duration).由於timestamp是在不斷隨著時間增長的,所以發生過運動的畫素點維持的 最長時間為duration.當mhi(x,y)保持的時間超過duration後,若在(x,y)處沒有發生新的運動,就令mhi(x,y)為零。
(3)mhi(x,y) = mhi(x,y) otherwise.只要發生過運動的畫素點維持的時間沒有超過duration,那麼令mhi(x,y)的大小維持發生運動的那個時刻的時間標記。
下面給出基於opencv2.0的程式碼,程式碼參考了opencv安裝目錄中的例程,並做了一些改動,方便其他專案中直接呼叫函式進行運動目標檢測。
#include <cv.h> #include <highgui.h> #include <time.h> void updateMhi(const IplImage* src_image,IplImage* binary_mhi) { //運動畫素維持的最大時間,單位與timestamp的單位一致 #define MHI_DURATION 1 //時間標記 double timestamp = clock()/100.; //當前幀的上一幀影象 static IplImage* last_image = NULL; static IplImage* color_silh = NULL; static IplImage* gray_silh = NULL; //運動歷史影象 static IplImage* mhi = NULL; if(NULL==last_image && NULL==color_silh && NULL==gray_silh && NULL==mhi) { CvSize size = cvGetSize(src_image); //初始分配記憶體,在該程式中沒有釋放如下影象的記憶體空間 last_image = cvCreateImage(size,8,3); color_silh = cvCreateImage(size,8,3); gray_silh = cvCreateImage(size,8,1); mhi = cvCreateImage(size,IPL_DEPTH_32F,1); //初始情況下令當前幀與上一幀影象相同 cvCopy(src_image,last_image); //置零初始運動歷史影象 cvZero(binary_mhi); } else { //獲得幀差影象color_silh cvAbsDiff(src_image,last_image,color_silh); cvCopy(src_image,last_image); cvCvtColor(color_silh,gray_silh,CV_BGR2GRAY); cvThreshold( gray_silh, gray_silh, 30, 255, CV_THRESH_BINARY); //更新運動歷史影象 cvUpdateMotionHistory(gray_silh,mhi,timestamp,MHI_DURATION); //將浮點型的運動歷史影象轉換成影象binary_mhi cvCvtScale( mhi, binary_mhi, 255./MHI_DURATION, (MHI_DURATION - timestamp)*255./MHI_DURATION ); //二值化 cvThreshold( binary_mhi, binary_mhi, 0, 255, CV_THRESH_BINARY ); } } int main() { CvCapture* capture = cvCreateFileCapture("D:\\technology\\CV\\Databases\\vedio\\motion.avi"); if(capture) { IplImage* frame = NULL; int width = (int)cvGetCaptureProperty(capture,CV_CAP_PROP_FRAME_WIDTH); int height = (int)cvGetCaptureProperty(capture,CV_CAP_PROP_FRAME_HEIGHT); CvSize frame_size = cvSize(width,height); IplImage* binary_mhi = cvCreateImage(frame_size,8,1); IplImage* src_image = cvCreateImage(frame_size,8,3); while(frame = cvQueryFrame(capture)) { cvCopy(frame,src_image); updateMhi(src_image,binary_mhi); cvNamedWindow("src"); cvShowImage("src",frame); cvNamedWindow("mhi"); cvShowImage("mhi",binary_mhi); if(27==cvWaitKey(33)) break; } cvReleaseCapture(&capture); cvDestroyWindow("src"); cvDestroyWindow("mhi"); cvReleaseImage(&src_image); cvReleaseImage(&binary_mhi); } return 0; }
程式執行的截圖如下: