Ask Your Question
1

Save repeatedly 5 data and do averaging after 5 frames in video processing

asked 2015-03-04 01:46:00 -0600

zms gravatar image

Hello, In a main loop opencv C++ for the video processing frame by frame, how can it possible for me to save the value for each of 5 frames and do averaging and then make decision, and then continuously process the next 5 frames and do the same thing (averaging and make decision).

In c++, i'm looking at the array method, to save the data, but i'm pretty sure I do not know how to interrupt to do something after 5 big loop and then continue with the next 5 loops. Please help if anyone have idea to do this.

Thanks Zamani

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
0

answered 2015-03-04 02:18:39 -0600

updated 2015-03-04 02:19:49 -0600

you can use cv::addWeighted to sum up the images. Assume that you have an empty image in which you want to store the images (dst) and read the video frames into a matrix src. your code could then look like (just pseudo-Code):

 cnt = 0;
 dst = EmptyImageSameSizeAsVideoSource() 
 while true:
    src = loadNewFrameFromStream()
    cv::addWeighted(dst,1,src,0.2,dst) # dst += 0.2*src 
    cnt = cnt +1;
    if cnt%5 == 0:
       DoSomeMagic(dst) # dst is your mean image!
       dst.setTo(0)
edit flag offensive delete link more
0

answered 2015-03-04 02:19:51 -0600

LBerger gravatar image

updated 2015-03-04 03:39:23 -0600

Hi, I'm not sure but may be you want to something like this:

VideoCapture *captureVideo=new VideoCapture(0);
    Mat frame[5];
    double x[5];
    for(;true;)
        {
        for (int nb=0;nb<5;)
            {
            if (captureVideo->retrieve(frame[nb])) // get a new frame from camera
                {
                x[nb]= MyFunction(frame[nb]);
                nb++;
                // 
                }
            }
        MyFunction5Results(x);
        }
edit flag offensive delete link more

Comments

ok let me try to digest and try.. thanks for opening the path! :)

zms gravatar imagezms ( 2015-03-04 02:26:14 -0600 )edit

but you only store a single double for each image so that you can't create the mean image. And why do you move the nb++; into the loop?

FooBar gravatar imageFooBar ( 2015-03-04 02:31:52 -0600 )edit

nb is into the loop because you want five images. If you write it into for() you're not sure to have acquire 5 images into the array if your function is very short in time. I think that you want to use a real camera and not video stream I'm sorry but I have a mistake in reading you question. If you want to make a decision using mean image (5 images) may be you should use a recursive filter (butterworth for example). With recursive filter you have an updated mean value after acquire : Im(t)=Im(t-1)+k*I(t)

LBerger gravatar imageLBerger ( 2015-03-04 02:57:27 -0600 )edit

"If you write it into for() you're not sure to have acquire 5 images into the array if your function is very short in time." What do you mean by that?

FooBar gravatar imageFooBar ( 2015-03-04 03:17:49 -0600 )edit

In opencv doc : The methods/functions decode and return the just grabbed frame. If no frames has been grabbed (camera has been disconnected, or there are no more frames in video file), the methods return false and the functions return NULL pointer. So if you write something like this with a real camera:

captureVideo->retrieve(frame[0]);
captureVideo->retrieve(frame[1]); // frame[1] is empty
captureVideo->retrieve(frame[2]); // frame[2] is empty

but if you write

   captureVideo->retrieve(frame[0]);
    sleep(30); // wait 30ms
    captureVideo->retrieve(frame[1]); // frame should be OK
    sleep(30);
    captureVideo->retrieve(frame[2]);  // frame should be OK
LBerger gravatar imageLBerger ( 2015-03-04 03:49:18 -0600 )edit

Sorry, I misread you code a bit. Moving the increment inside the check of the return values makes perfekt sense.

FooBar gravatar imageFooBar ( 2015-03-04 03:58:44 -0600 )edit

Hi FooBar and LBerger, thanks informative for the discussion, anyway, it is not the whole image mean. Currently i'm doing the pixel count --> countNonZero(frame) for each of the images. Then this 5 values from 5 images must be average and use as the result for the last function. so, the above coding can be done?

zms gravatar imagezms ( 2015-03-04 23:43:43 -0600 )edit

you can use function calcHist (instead of MyFunction) with a mask and check if h(0] is equal to the mask surface. An another way it's to scan pixel in the mask and stop when a non null pixel is found. May be you should give your code and like this it woul be easier to check

LBerger gravatar imageLBerger ( 2015-03-05 02:40:26 -0600 )edit

Here is the code ..

while(1) {

    bool bSuccess = cap.read(frame); // read a new frame from video

    if (!bSuccess) //if not success, break loop
    {
                    cout << "Cannot read the frame from video file" << endl;
                    break;
    }

    //do video processing

     //*averaging pixels for 5 frames
     if(count != 5)
     {
         totalpix5 += whitepix;
        cout << "totalpix5 = "<< endl << " "  <<totalpix5<< endl;
        count++;
     }

     if(count == 3)
     {

     if (totalpix5/5 >2500)  
     {
     putText();
     }
     else
        {   
        putText();
        }

        imshow("detected", cdst);    
     count=0;
     totalpix5=0;
     }

waitKey(); return 0; }

zms gravatar imagezms ( 2015-03-05 03:20:54 -0600 )edit

May be you can use calcHist with cumulate histogram

        for (;;) 
        {
        hist[0]=Mat::zeros(Size(1,sizes[0]),CV_32F);
        hist[1]=Mat::zeros(Size(1,sizes[0]),CV_32F);
        hist[2]=Mat::zeros(Size(1,sizes[0]),CV_32F);
        for (int nb=0;nb<5;)
            {
            if (capture.retrieve(frame[nb])) 
                {
                cout<<"*******Image "<<nb<<endl;
                int nbc=2;
                if (frame[nb].empty())
                    break;
                imshow(window_name, frame[nb]);
                split( frame[nb], planCouleur );
                for (int i=0;i<frame[nb].channels();i++)
                    {
                    calcHist(&planCouleur[i],1,channels,mask, hist[i], 1, sizes, listRange, true, true);
                    cout<<"Plane "<<i<<"\t"; 
                    for (int j=0;j<sizes[0];j++)
                        cout<<"h["<<j<<"]="<<hist[i].at<float>(j,0)<<"\t";
                    cout<<endl;
                    }
                nb++;
                }
             }
        }
LBerger gravatar imageLBerger ( 2015-03-05 09:27:59 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-03-04 01:46:00 -0600

Seen: 732 times

Last updated: Mar 04 '15