0

I've written this code

while (true)
{
    cv::Mat frame1,frame2,dst,temp;
    if (!input_video.read(frame1))
    {
        fprintf(stderr, "Video has Finished .\n");
        getchar();
        return -1;
    }
    if (!input_video.read(frame2))
    {
        fprintf(stderr, "Video has Finished .\n");
        getchar();
        return -1;
    }
    cv::cvtColor(frame1,frame1,CV_RGB2GRAY) ;
    cv::cvtColor(frame2,frame2,CV_RGB2GRAY) ;
    cv::subtract(frame2,frame1,dst);
    cv::imshow("F1",frame1);
    cv::imshow("F2",frame2);
    cv::imshow("dst",dst);
    cv::waitKey();
       }

and When I'm reading a video (not from a camera but a video from my hard disk) frame1,frame2 are the same !!!

I don't know why "read" method returns the same frame for frame2 ? so the subtracted image is always an empty picture !!!

should I do something especial for reading sequential frames simultaneously ? for example every time I want to read another frame use this line to get to that frame :

      input_video.set(CV_CAP_PROP_POS_FRAMES,current_frame+1);

if so, is there another way not doing this ?!

Thanks

PsP
  • 696
  • 3
  • 10
  • 34
  • http://stackoverflow.com/q/11469281/2065121 – Roger Rowland Jul 13 '13 at 08:07
  • Yes I've read that but the answers did not worked for me ! I mean in this code the result is always zero (even for key frames !!!) it seems that frame1,frame2 is always the same ... – PsP Jul 13 '13 at 09:10

1 Answers1

1

The function input_video.read() doesn't create new object every time you call it and returns a pointer of an internal buffer of cv::VideoCapture. For this case if you copy first frame to a cv::Mat object, problem is resolved:

while (true)
{
    cv::Mat frame,frame1,frame2,dst,temp;
    if (!input_video.read(frame))
    {
        fprintf(stderr, "Video has Finished .\n");
        getchar();
        return -1;
    }
    frame.assignTo(frame1);
    if (!input_video.read(frame))
    {
        fprintf(stderr, "Video has Finished .\n");
        getchar();
        return -1;
    }
    frame.assignTo(frame2);
    cv::cvtColor(frame1,frame1,CV_RGB2GRAY) ;
    cv::cvtColor(frame2,frame2,CV_RGB2GRAY) ;
    cv::subtract(frame2,frame1,dst);
    cv::imshow("F1",frame1);
    cv::imshow("F2",frame2);
    cv::imshow("dst",dst);
    cv::waitKey();
       }
Nima
  • 379
  • 3
  • 15
  • did you miss to put a frame.assignTo(frame2); in your code after we read frame2 ?, since we're looping in video frames , in the next iteration it might happen that we read frame2 instead of frame1 ?! – PsP Jul 14 '13 at 08:19
  • I changed it but not for that reason, because in next lines 'cv::cvtColor(frame2,frame2,CV_RGB2GRAY)' modifies 'frame2' contents. – Nima Jul 14 '13 at 12:42
  • +1 & accepting the answer, just one thing you mean that every time I read a frame I should perform some calculation on it, then read another one , so this makes "read" method to read another frame ? – PsP Jul 14 '13 at 13:37
  • No, the method cv::VideoCapture::read() grab the next frame every time you call it, but it don't create new cv::Mat for every frame and only writes new frame contents into an internal buffer of cv::VideoCapture and passes the pointer to you so contents will change for every time you call read() method also you shouldn't modify or release them. actually in you code frame1 and frame2 have the same address that points to cv::VideoCapture internal buffer so you see both frames like each other. – Nima Jul 15 '13 at 07:33