# Why don't means of color channels average to equal flattened array mean

I am experimenting with different types of mean subtraction on RGB images for a convolutional neural network. I tried calculating a single grand mean of all the training images. I also tried calculating a mean per color channel. The grand mean I got was 122.84 which sounds like a reasonable number. However, when I tried calculating the means per color channel I got [4.86049, 4.86049, 4.86049]. First off, I find it strange that they are all the same number. Secondly, they seem ridiculously low. And thirdly and perhaps most confusingly, shouldn't the mean of the three color channels equal the grand mean?

Maybe it is a problem with my code? This is what I'm using. The images are in a numpy array of the shape (17611, 224, 224, 3)

trainImgsArr = np.random.rand(17611, 224, 224, 3)
grandMean = np.mean(trainImgsArr)
meanByChannel = np.mean(trainImgsArr, axis = (0,1,2))


Any ideas?

EDIT: Ah, ha! I think I have found the true channel means with the code

 ch1, ch2, ch3 = np.split(trainImgsArr, 3, axis = 3)
np.mean(ch1)
np.mean(ch2)
np.mean(ch3)


Sorry if this was super basic I am very new to python. Could someone perhaps explain where I went wrong using a single np.mean call as in the first code bit?

• How did you even get 122's and 4.xx' at the first place? numpy.random.rand generates values between 0 and 1. Is it not the case in your problem? Jun 24, 2018 at 5:17
• The random numbers were just to provide an example. My actual images are pixel values between 0-255 Jun 24, 2018 at 5:40

You just understood numpy wrong (God bless those who understood it right). The correct code should have been:

trainImgsArr = np.random.rand(17611, 224, 224, 3)
grandMean = np.mean(trainImgsArr)
meanByChannel = []
for i in range(0, 3):
avg = np.mean(trainImgsArr[:, :, :, i]
meanByChannel.append(avg)


Basically I am doing splicing of the array,taking all pixels of a colour channel from all images and averaging them. Whereas you did something else entirely (your results are not reproducible). Axes (0, 1, 2) does not mean the colour channels it only means the index you are referring to and performing the required operation. Ignore the convolution part but check the subscripts of h_n-1 you can access the those positions by varying the last argument in trainImgsArr.shape.

• Thank you for the solution! What I thought the axis argument of np.mean did was collapse across those three axes, yielding 1 mean for each color channel. Still not quite sure what it actually does or why I was getting the wrong answer, but it seems as though both my edit and your answer get the correct solution! Jun 26, 2018 at 16:44
• @user7498750 see you are varying channels rgb here but where is this channel nfo encoded? it is encoded in the 4th index as the number 3, which means 3 channels so (a,b,c,0) will mean pixel in 1st channel, (a,b,c,1) pixel in same position but second channel Jun 26, 2018 at 19:08