我正在尝试使用简单的动作检测代码来检测来自相机的移动。我正在使用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;
}
任何帮助将不胜感激!
答案 0 :(得分:1)
如果您正在寻找一种简单的方法,我会使用img_diff的平均值作为运动参数,只需将平均值与5或10的阈值进行比较(假设为8位灰色):
if(mean(img_diff) > thresval){
cout << "motion detected!" << endl;
}
使用此方法,您无需将阈值调整为图像大小。 然而,我看到仅使用当前帧和前一帧检测运动的一般问题:它将仅检测高频运动,或者换句话说仅检测快速运动。如果要检测慢动作,则需要将当前帧与较旧的帧进行比较,如之前的5帧或10帧。