maxl
maxl

Reputation: 1

c++ Opencv accumulateWeighted - strange behaviour

I'm trying to get an running average of frames from my cam, but after a few secounds the image of the averaged frames gets brighter and brighter and than white.

my cam provides an image in gray scale with 3 channels. I'm on windows 7, Visualstudio 2012, opencv 243

#include<opencv2\opencv.hpp>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;


int main(int argc, char* argv[])
{
    VideoCapture cap(0);
    Mat frame1;
    cap.read(frame1);
    Mat acc = Mat::zeros(frame1.size(), CV_32FC1);

    while(1){
        Mat frame;
        Mat gray;
        cap.read(frame);
        cvtColor(frame ,gray ,CV_BGR2GRAY,0);
        accumulateWeighted(gray, acc,0.005);
        imshow("gray", gray);
        imshow("acc", acc);
        waitKey(1); //don't know why I need it but without it the windows freezes
    }
}

can anyone tell me what i did wrong? Thanks!

Upvotes: 0

Views: 7404

Answers (2)

user3727794
user3727794

Reputation: 13

I found a more elegant solution for this question. The function that you need is already provided by OpenCV. This works on 3-channel color or 1-channel grayscale images:

Method convertScaleAbs

Inline documentation

scales array elements, computes absolute values and converts the results to 8-bit unsigned integers: dst(i)=saturate_castabs(src(i)*alpha+beta)

Signature

convertScaleAbs(InputArray src, OutputArray dst, double alpha=1, double beta=0)

Example code

// Variables
Mat frame;
Mat accumulator;
Mat scaled;

// Initialize the accumulator matrix
accumulator = Mat::zeros(frame.size(), CV_32FC3);

while(1){
   // Capture frame
   capture >> frame;

   // Get 50% of the new frame and add it to 50% of the accumulator
   accumulateWeighted(frame, accumulator, 0.5);

   // Scale it to 8-bit unsigned
   convertScaleAbs(accumulator, scaled);

   imshow("Original", frame);

   imshow("Weighted Average", scaled);

   waitKey(1);
}

Upvotes: 1

Aubrey da Cunha
Aubrey da Cunha

Reputation: 506

The issue here is with how imshow maps matrix values to pixel values. Typically, the raw data from the cam comes in as an integer data type, typically in the range [0, 255]. The accumulateWeighted function does what you expect and computes a running average of the frames. So acc is a floating-point matrix with values somewhere in [0, 255].

Now, when you pass that matrix to imshow, the matrix values need to get mapped to intensities. Since the datatype is a floating-point type, 0 gets mapped to black, 1 gets mapped to white and everything outside that range gets clipped. Thus, only if a region of your image is very dark and stays that way, will the running average stay below 1 and get mapped to a color other than pure white.

Luckily, the fix is simple:

imshow("acc", acc/255);

Upvotes: 3

Related Questions