0

I'm trying to play with my webcam and OpenCV. I follow this tuto : http://mateuszstankiewicz.eu/?p=189. But the only result I have is one red border and I don't understand why. Could anyone help me to make it right and fix this ?

Here is my code :

#include "mvt_detection.h"


Mvt_detection::Mvt_detection()
{

}

Mvt_detection::~Mvt_detection()
{
}

cv::Mat Mvt_detection::start(cv::Mat frame)
{
    cv::Mat back;
    cv::Mat fore;
    cv::BackgroundSubtractorMOG2 bg(5,3,true) ;
    cv::namedWindow("Background");
    std::vector<std::vector<cv::Point> > contours;

    bg.operator ()(frame,fore);
    bg.getBackgroundImage(back);
    cv::erode(fore,fore,cv::Mat());
    cv::dilate(fore,fore,cv::Mat());
    cv::findContours(fore,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
    cv::drawContours(frame,contours,-1,cv::Scalar(0,0,255),2);
    return frame;
}

Here is a screenshot of what our cam returns : enter image description here

I tried on two other video from there and there and there is the same issue.

Thanks for the help :).

ogdabou
  • 582
  • 1
  • 10
  • 41
Lenjyco
  • 41
  • 1
  • 1
  • 7
  • can you add a `cv::namedWindow("foreground"); cv::imshow("foreground",fore); cv::waitKey(30);` ? There you can see whether the motion COULD be detected in the image. If no foreground is visible, the background subtraction isn't well suited for your problem. Example images/videos would be nice, too! – Micka Jan 20 '14 at 10:47
  • 1
    hi, I'm on the same project (we are students adn it's a school project). And I tried to show the `fore` image. The image is all black. So, I guess we cannot use this method ? Is it because the webcam hasn't enough quality capacity ? Thanks – ogdabou Jan 20 '14 at 11:10
  • @Micka : I get a white window when the 3rd arg of `cv::BackgroundSubtractorMOG2 bg(5,3,true) ;` is `true` and black window when it is `false` – Lenjyco Jan 20 '14 at 11:35
  • The simplest way to do this, is to take an image of the entire background, and then take the absolute difference between your background, and the image with you in it. Try to see if you can get that to work first. – Dyrborg Jan 20 '14 at 11:47
  • @Dyrborg: `bg.operator ()(frame,fore);` don't do this ? – Lenjyco Jan 20 '14 at 11:49
  • If you want to implement your own foreground extraction, you could try ViBe http://www.vibeinmotion.com/Product/Literature.aspx It's very easy to implement and quite good, but patented so you can't use it for any real projects ;) – Micka Jan 20 '14 at 12:10
  • I am unsure how it works with OpenCV functions. When I did this I just used absdiff(InputArray back, InputArray fore, OutputArray output). Output then show exactly where your moving object is. – Dyrborg Jan 20 '14 at 12:11
  • It might also help to blur every image slightly to get rid of the cheap webcam noise! – Sebastian Schmitz Jan 20 '14 at 12:49
  • both sample videos don't have a (not even nearly) constant background, so I'll try some samples from http://changedetection.net/ – Micka Jan 20 '14 at 13:41
  • ok, there's at least one problem: you open the camera somewhere else and call `start(cv::Mat frame)` for each frame? A new `backgroundSubtractor` would be created for each frame, so there is no background to subtract from the input image yet. – Micka Jan 20 '14 at 13:58
  • @Micka : Yes it is, I tried in another version to create the `backgroundSubtractor` in the same place where I open the camera and pass it with `cv::Mat frame` but still got the same pb – Lenjyco Jan 20 '14 at 14:05
  • @Micka : do I need the previous frame to do the backgroundsubstration ? – Lenjyco Jan 20 '14 at 14:43
  • if you say that the previous frame is your background model, that would be the easiest background subtraction method and can only detect current movements. To use it just compute `(frame - previous)>threshold`. Otherwise: Testing a little bit with images from the database the `BackgroundSubtractorMOG2` works but I had to adjust the parameters (much noisy foreground otherwise and history much too small) and the background image included new images too fast. If you remove all the erode and dilate and contour stuff, there is no foreground image either? how does your background image look like? – Micka Jan 20 '14 at 15:29
  • 1
    Problem fixed, putting `BackgroundSubtractorMOG2` in my object's field and initialise it in constructor make him work well. TY all for contributions. – Lenjyco Jan 20 '14 at 15:59
  • 1
    that's what I meant earlier! You mentioned that you tried providing it as a parameter in function call, but there you would have to pass the parameter `by reference`! Just for you to understand what went wrong there. – Micka Jan 20 '14 at 17:20

3 Answers3

0

I have used the following code which is similar to yours and it is working well. I am also taking the inputs from my webcam. In your code, i didnt find any imshow() and waitkey. Try to use them. My code is following:

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/video/background_segm.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdio.h>

#include <iostream>
#include <vector>

using namespace std;
using namespace cv;

int main()
{

    VideoCapture cap;
    bool update_bg_model = true;

    cap.open(0);
    cv::BackgroundSubtractorMOG2 bg;//(100, 3, 0.3, 5);
    bg.set ("nmixtures", 3);
    std::vector < std::vector < cv::Point > >contours;

    cv::namedWindow ("Frame");
    cv::namedWindow ("Background");

    Mat frame, fgmask, fgimg, backgroundImage;

    for(;;)
    {
        cap >> frame;
        bg.operator()(frame, fgimg);
        bg.getBackgroundImage (backgroundImage);
        cv::erode (fgimg, fgimg, cv::Mat ());
        cv::dilate (fgimg, fgimg, cv::Mat ());

        cv::findContours (fgimg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
        cv::drawContours (frame, contours, -1, cv::Scalar (0, 0, 255), 2);

        cv::imshow ("Frame", frame);
        cv::imshow ("Background", backgroundImage);


        char k = (char)waitKey(30);
        if( k == 27 ) break;

    }

    return 0;
}
skm
  • 5,015
  • 8
  • 43
  • 104
  • I followed your code. But i got this error.. "ld: 1 duplicate symbol for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation)" – Hussaan S Jul 23 '14 at 08:17
0

Problem fixed, putting BackgroundSubtractorMOG2 in my object's field and initialise it in constructor make him work well.

Lenjyco
  • 41
  • 1
  • 1
  • 7
0

As @Lenjyco said, we fixe the problem.

@Micka had a good idea :

Firstly the BackgroundSubtractorMOG2 as to be instancied only ONCE.

We instantiate it in the constructor and play with the Hystory and Threashold:

Mvt_detection::Mvt_detection()
{
    bg = new cv::BackgroundSubtractorMOG2(10, 16, false);
}

10 : the number of image the backgound look back to compare.

16 : the threshold level (blur)

This way, we are now able to detect motion.

Thank you !

ogdabou
  • 582
  • 1
  • 10
  • 41