简体   繁体   中英

motion detection opencv

I am attempting to use a straightforward motion detection code to detect movement from a camera. I'm using the OpenCV library and I have some code that takes the difference between two frames to detect a change and then it uses a threshold to create a black/white image of the difference.

My problem: I cannot figure out a simple way to get a true or false output if motion is detected. I got this code from somewhere else and I am not familiar with all the details. I tried to sum the img_diff matrix but it gave me an error. What would be the simplest way to get a 'true' output if motion is detected, meaning that the background difference is not zero? For example, would an if statement comparing two matrices of the current frame and previous frame work?

The code I'm trying to use is below:

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;

}

Any help would be appreciated!

If you are looking for an easy way i would use the average of img_diff as a parameter for motion and just compare the average with a threshold of like 5 or 10 (assuming 8bit gray):

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

Using this method you don't have to adjust your threshold to the size of the images. However i see a general problem with detecting motion using only the current and previous frame: it will only detect high frequency motion, or in other words only fast motion. If you want to detect slow motion you need to compare the current frame to an older frame, like 5 or 10 frames before.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM