OpenCV运动检测

3
我想使用一个简单的运动检测代码来检测摄像头的移动。我正在使用OpenCV库,并且有一些代码可以获取两个帧之间的差异来检测变化,然后它使用阈值来创建差异的黑白图像。
我的问题是:我无法找到一个简单的方法来获得true或false输出,如果检测到运动。我从别处获取了这段代码,不熟悉所有细节。我试图求和img_diff矩阵,但它给了我一个错误。什么是最简单的方法来获得“true”输出,如果检测到运动,这意味着背景差异不为零?例如,比较当前帧和上一帧的两个矩阵的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 - Quentin Geissmann
1个回答

1
如果你正在寻找一种简单的方法,我会将img_diff的平均值作为运动的参数,并将平均值与阈值(假设为8位灰度)进行比较,例如5或10。
  if(mean(img_diff) > thresval){
    cout << "motion detected!" << endl;
  }

使用这种方法,您不需要调整阈值来适应图像的大小。然而,我发现仅使用当前和先前帧来检测运动存在一个普遍问题:它只会检测高频运动,或者换句话说只检测快速运动。如果您想检测慢动作,则需要将当前帧与早期帧(如5或10帧之前)进行比较。

我没有计算机视觉方面的经验。所以你能否解释一下为什么会发生这种情况?两个帧之间会有一些差异,为什么不能考虑到这些差异呢? - timemanx
1
问题在于即使没有任何运动,两个帧之间总是存在差异。这是由于传感器噪声造成的,其范围约为1%至5%,具体取决于照明情况。因此,您需要足够大的差异来确保您检测到的“运动”实际上不是噪声。 - Hugo Maxwell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接