2012-11-28 92 views
3

我正在嘗試使用直觀的運動檢測代碼來檢測攝像頭的運動。我使用的是OpenCV庫,我有一些代碼使用兩幀之間的差異來檢測變化,然後使用閾值創建差異的黑白圖像。運動檢測opencv

我的問題:我找不到一個簡單的方法來檢測到運動時得到真或假的輸出。我從其他地方獲得了這些代碼,並且我不熟悉所有細節。我試圖總結img_diff矩陣,但它給了我一個錯誤。如果檢測到運動,那麼獲得「真實」輸出的最簡單方法是什麼?這意味着背景差異不是零?例如,if語句會比較當前幀和前一幀的兩個矩陣嗎?

我試圖使用的代碼如下:

int main(int argc, char** argv) 
{ 
const char * _diffType = getCmdOption("-type", "2", argc, argv); 
const char * _thresval = getCmdOption("-thr", "60", argc, argv); 

int diffType = atoi(_diffType); 
int thresval = atoi(_thresval); 

VideoCapture cap(0); 
if(!cap.isOpened()) return -1; 

Mat cam_frame, img_gray, img_prev, img_diff, img_bin; 

const char *win_cam = "Camera input"; namedWindow(win_cam, CV_WINDOW_AUTOSIZE); 
const char *win_gray = "Gray image"; namedWindow(win_gray, CV_WINDOW_AUTOSIZE); 
const char *win_diff = "Binary diff image"; namedWindow(win_diff, CV_WINDOW_AUTOSIZE); 

bool first_frame = true; 
while (cvWaitKey(4) == -1) { 
cap >> cam_frame; 
cvtColor(cam_frame, img_gray, CV_BGR2GRAY); 

if (first_frame) { 
img_prev=img_gray.clone(); 
first_frame = false; 
continue; 
} 

absdiff(img_gray, img_prev, img_diff); 
threshold(img_diff, img_bin, thresval, 255, THRESH_BINARY); 
erode(img_bin, img_bin, Mat(), Point(-1,-1), 3); 
dilate(img_bin, img_bin, Mat(), Point(-1,-1), 1); 

imshow(win_cam, cam_frame); 
imshow(win_gray, img_gray); 
imshow(win_diff, img_bin); 

if (diffType == 1) img_prev=img_gray.clone(); 
} 

return 0; 

} 

任何幫助,將不勝感激!

+1

你好,你說你試圖「總結img_diff矩陣」,但它給了一個錯誤。我會建議計算非零的比例 - 使用'cv :: countNonZero' - 像素在你的二進制圖像(膨脹後)。 –

回答

1

如果你正在尋找一個簡單的方法我會用img_diff的平均值作爲用於運動的參數,並且只用5或10個(假定8位灰度)的像的閾值比較的平均值:

if(mean(img_diff) > thresval){ 
    cout << "motion detected!" << endl; 
    } 

使用這種方法,您不必將圖像的大小調整爲閾值。然而,我發現只使用當前幀和前一幀檢測運動的一般問題:它只會檢測高頻運動,或者換句話說,只檢測快速運動。如果您想檢測慢動作,您需要將當前幀與較早的幀進行比較,例如之前的5或10幀。

+0

我對計算機視覺沒有經驗。那麼你能否解釋爲什麼會發生這種情況。這兩個框架之間會有一些差異。爲什麼不這樣做呢? –

+1

問題是,即使根本沒有任何動作,兩個框架之間始終存在差異。這是因爲傳感器噪聲取決於照明在1%到5%左右。所以你需要足夠高的差別來確保你正在檢測的「運動」實際上不是噪音。 –

+0

好的。我知道了。 –