Reputation: 1
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
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:
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)
// 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
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