user1858302
user1858302

Reputation: 31

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!

Upvotes: 3

Views: 7105

Answers (1)

Hugo Maxwell
Hugo Maxwell

Reputation: 763

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.

Upvotes: 1

Related Questions