# How to take average every X frames

Hi, I want to take average of every 15 images

This is currently what I have:

int main() {
VideoCapture cap(0); // open the default camera
if (!cap.isOpened())  // check if we succeeded
return -1;
cap.set(CV_CAP_PROP_FPS, 15);

std::vector<cv::Mat> images(9000);
{
Mat frame;
cap >> frame;
if (frame.empty()) break; // end of video stream
if (waitKey(1) == 27) break; // stop capturing by pressing ESC
}
for (int i = 0; i < 600; i++)
{
Mat avgImg(480, 640, CV_32FC3, Scalar());
{
}
//stacking every 15 images into a single image
avgImg = avgImg / 15;
avgImg.convertTo(avgImg, CV_8UC3);
char filename[80];
imwrite(filename, avgImg);


However, this will need me to create a vector of 9000 images, which is a bit excessive. Is there a way for me to accomplish this without having to use a vector?

edit retag close merge delete

forget vector images

use an index i in loop framenumb to count frame from 0 to 14 and accumulate image (like you have already done)

( 2016-11-10 14:10:09 -0500 )edit

Sort by ยป oldest newest most voted

you should not cache thousands of images in a vector to achieve this, rather use a (short) ringbuffer for the desired accumulation, and do it all online

c++ also has more containers than vector, we can use a std::deque here, and simply push the most recent image into one end, and pop the oldest image at the other end (fifo)

#include <opencv2/opencv.hpp>
#include <iostream>
#include <deque>

using namespace cv;
using namespace std;

int main()
{
std::deque<cv::Mat> ring;

VideoCapture cap(0);
if (!cap.isOpened())
return -1;

while(true)
{
Mat frame;
cap >> frame;
if (frame.empty()) break;

ring.push_back(frame);
if (ring.size() > 15)
{
ring.pop_front();

Mat avgImg(frame.size(), CV_32FC3, Scalar());
for (int i=0; i<15; i++)
accumulate(ring[i], avgImg);

avgImg.convertTo(avgImg, CV_8UC3, 1.0/15);
imshow("avg", avgImg);
}

imshow("webcam", frame);
if (waitKey(10) > 0) break;
}
return EXIT_SUCCESS;
}

more

Official site

GitHub

Wiki

Documentation