user2769614
user2769614

Reputation: 247

Average set of color images and standard deviation

I am learning image analysis and trying to average set of color images and get standard deviation at each pixel

I have done this, but it is not by averaging RGB channels. (for ex rchannel = I(:,:,1))

filelist = dir('dir1/*.jpg');
ims = zeros(215, 300, 3);
for i=1:length(filelist)
    imname = ['dir1/' filelist(i).name];
    rgbim = im2double(imread(imname));
    ims = ims + rgbim;
end

avgset1 = ims/length(filelist);
figure;
imshow(avgset1);

I am not sure if this is correct. I am confused as to how averaging images is useful. Also, I couldn't get the matrix holding standard deviation.

Any help is appreciated.

Upvotes: 1

Views: 1310

Answers (1)

rayryeng
rayryeng

Reputation: 104484

If you are concerned about finding the mean RGB image, then your code is correct. What I like is that you converted the images using im2double before accumulating the mean and so you are making everything double precision. As what Parag said, finding the mean image is very useful especially in machine learning. It is common to find the mean image of a set of images before doing image classification as it allows the dynamic range of each pixel to be within a normalized range. This allows the training of the learning algorithm to converge quickly to the optimum solution and provide the best set of parameters to facilitate the best accuracy in classification.


If you want to find the mean RGB colour which is the average colour over all images, then no your code is not correct.

You have summed over all channels individually which is stored in sumrgbims, so the last step you need to do now take this image and sum over each channel individually. Two calls to sum in the first and second dimensions chained together will help. This will produce a 1 x 1 x 3 vector, so using squeeze after this to remove the singleton dimensions and get a 3 x 1 vector representing the mean RGB colour over all images is what you get.

Therefore:

mean_colour = squeeze(sum(sum(sumrgbims, 1), 2));

To address your second question, I'm assuming you want to find the standard deviation of each pixel value over all images. What you will have to do is accumulate the square of each image in addition to accumulating each image inside the loop. After that, you know that the standard deviation is the square root of the variance, and the variance is equal to the average sum of squares subtracted by the mean squared. We have the mean image, now you just have to square the mean image and subtract this with the average sum of squares. Just to be sure our math is right, supposing we have a signal X with a mean mu. Given that we have N values in our signal, the variance is thus equal to:

Variance

Source: Science Buddies

The standard deviation would simply be the square root of the above result. We would thus calculate this for each pixel independently. Therefore you can modify your loop to do that for you:

filelist = dir('set1/*.jpg');
sumrgbims = zeros(215, 300, 3);
sum2rgbims = sumrgbims; % New - for standard deviation
for i=1:length(filelist)
    imname = ['set1/' filelist(i).name];
    rgbim = im2double(imread(imname));
    sumrgbims = sumrgbims + rgbim;
    sum2rgbims = sum2rgbims + rgbim.^2; % New
end

rgbavgset1 = sumrgbims/length(filelist);

% New - find standard deviation
rgbstdset1 = ((sum2rgbims / length(filelist)) - rgbavgset.^2).^(0.5);

figure;
imshow(rgbavgset1, []);

% New - display standard deviation image
figure;
imshow(rgbstdset1, []);

Also to make sure, I've scaled the display of each imshow call so the smallest value gets mapped to 0 and the largest value gets mapped to 1. This does not change the actual contents of the images. This is just for display purposes.

Upvotes: 3

Related Questions