Я пытаюсь использовать простой код обнаружения движения для обнаружения движения с камеры. Я использую библиотеку 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;
}
Любая помощь будет оценена!
Если вы ищете простой способ, я бы использовал среднее значение img_diff в качестве параметра для движения и просто сравнил среднее с пороговым значением, равным 5 или 10 (при условии 8-битного серого):
if(mean(img_diff) > thresval){
cout << "motion detected!" << endl;
}
Используя этот метод, вам не нужно настраивать порог в соответствии с размером изображений.
Однако я вижу общую проблему с обнаружением движения с использованием только текущего и предыдущего кадра: он будет обнаруживать только высокочастотное движение, или, другими словами, только быстрое движение. Если вы хотите обнаружить медленное движение, вам нужно сравнить текущий кадр со старым кадром, например, 5 или 10 кадров раньше.
Других решений пока нет …