9

i have 100 image, each one is 598 * 598 pixels, and i want to remove the pictorial and noise by taking the average of pixels, but if i want to use Adding for "pixel by pixel"then dividing i will write a loop until 596*598 repetitions for one image, and 598*598*100 for hundred of image.

is there a method to help me in this operation?

Karmel Zaidan
  • 153
  • 2
  • 2
  • 11
  • http://answers.opencv.org/question/7385/how-to-calculate-the-mean-value-of-multiple-pictures/ – Anantha Sharma Feb 27 '16 at 09:33
  • I'm not sure I correctly understood your question in my answer, could you please comment if I got it correctly ? – kebs Feb 27 '16 at 09:46
  • i want to take the mean of 100 image, my problem: if i take the mean by adding each pixel, my loop will do 598*598*100 = 25000000 repetition – Karmel Zaidan Feb 27 '16 at 10:12
  • May me use moving average ? https://en.wikipedia.org/wiki/Moving_average Also you may be interested in addWeigted method http://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html#addweighted – Andrey Smorodov Feb 27 '16 at 14:50

3 Answers3

5

You need to loop over each image, and accumulate the results. Since this is likely to cause overflow, you can convert each image to a CV_64FC3 image, and accumualate on a CV_64FC3 image. You can use also CV_32FC3 or CV_32SC3 for this, i.e. using float or integer instead of double.

Once you have accumulated all values, you can use convertTo to both:

  • make the image a CV_8UC3
  • divide each value by the number of image, to get the actual mean.

This is a sample code that creates 100 random images, and computes and shows the mean:

#include <opencv2\opencv.hpp>
using namespace cv;

Mat3b getMean(const vector<Mat3b>& images)
{
    if (images.empty()) return Mat3b();

    // Create a 0 initialized image to use as accumulator
    Mat m(images[0].rows, images[0].cols, CV_64FC3);
    m.setTo(Scalar(0,0,0,0));

    // Use a temp image to hold the conversion of each input image to CV_64FC3
    // This will be allocated just the first time, since all your images have
    // the same size.
    Mat temp;
    for (int i = 0; i < images.size(); ++i)
    {
        // Convert the input images to CV_64FC3 ...
        images[i].convertTo(temp, CV_64FC3);

        // ... so you can accumulate
        m += temp;
    }

    // Convert back to CV_8UC3 type, applying the division to get the actual mean
    m.convertTo(m, CV_8U, 1. / images.size());
    return m;
}

int main()
{
    // Create a vector of 100 random images
    vector<Mat3b> images;
    for (int i = 0; i < 100; ++i)
    {
        Mat3b img(598, 598);
        randu(img, Scalar(0), Scalar(256));

        images.push_back(img);
    }

    // Compute the mean
    Mat3b meanImage = getMean(images);

    // Show result
    imshow("Mean image", meanImage);
    waitKey();

    return 0;
}
Miki
  • 40,887
  • 13
  • 123
  • 202
3

Suppose that the images will not need to undergo transformations (gamma, color space, or alignment). The numpy package lets you do this quickly and succinctly.

# List of images, all must be the same size and data type.
images=[img0, img1, ...]
avg_img = np.mean(images, axis=0)

This will auto-promote the elements to float. If you want the as BGR888, then:

avg_img = avg_img.astype(np.uint8)

Could also do uint16 for 16 bits per channel. If you are dealing with 8 bits per channel, you almost certainly won't need 100 images.

mbells
  • 3,668
  • 3
  • 22
  • 21
1

Firstly- convert images to floats. You have N=100 images. Imagine that a single image is an array of average pixel values of 1 image. You need to calculate an array of average pixel values of N images.

Let A- array of average pixel values of X images, B - array of average pixel values of Y images. Then C = (A * X + B * Y) / (X + Y) - array of average pixel values of X + Y images. To get better accuracy in floating point operations X and Y should be approximately equal

You may merge all you images like subarrays in merge sort. In you case merge operation is C = (A * X + B * Y) / (X + Y) where A and B are arrays of average pixel values of X and Y images