Hossein
Hossein

Reputation: 25924

How to calculate mean for batch of images in Python in a non vectorized way?

In order to calculate the image mean, one can use numpy.mean() if I'm not mistaken.

What mean() does, is simply summing all elements and then dividing by the number of all elements summed. furthermore if I want to calculate mean channelwise,(each channel has its own mean calculated), and I have an input of shape: (num_batch, num_channel, width, height), I'd write :

numpy.mean(a,axis=(0,2,3)) 

Now, I tried to code its non vectorized version but I'm not sure I'm doing everything correctly.

This is the code that is presumed to be calculating the mean channel-wise, (its output should match that of the command given above:

def calc_mean_classic(a):
    #sum all elements in each channel and divide by the number of elements
    batch = a.shape[0]
    channel = a.shape[1]
    width = a.shape[2]
    height = a.shape[3]

    sum = np.zeros((channel))
    for i in range(batch):
        for c in range(channel):
            for w in range(width):
                for h in range(height):
                    sum[c] += a[i,c,w,h]

    return sum, (sum/(width*height))

When I run my data with numpy.mean(a,axis=(0,2,3)), I get :

[ 125.30691805  122.95039414  113.86538318]

but when I run the function I coded, I get :

sum,m3 = calc_mean_classic(data_train)
print 'sum=',sum
print 'm3=',m3
print m3[0]/(32*32)

Output:

sum= [  6.41571420e+09   6.29506018e+09   5.82990762e+09]
m3= [ 6265345.90234375  6147519.70703125  5693269.15917969]
6118.50185776

There is an irony here, image size is 32*32 that's why I'm doing m3[0]/(32*32) (sum/width*height) to see if I can generate the sum[0] value! As you can see they are completely different values, while they should yield the same value!

I have no idea what's going on here.

Upvotes: 2

Views: 3791

Answers (2)

Oscar Rangel
Oscar Rangel

Reputation: 1056

this worked for me, thanks!

    # YOUR CODE HERE
    a = batch.asnumpy()

    #sum all elements in each channel and divide by the number of elements
    batch = a.shape[0]
    channel = a.shape[1]
    width = a.shape[2]
    height = a.shape[3]

    sum = np.zeros((channel))
    for i in range(batch):
        for c in range(channel):
            for w in range(width):
                for h in range(height):
                    sum[c] += a[i,c,w,h]

    sum = sum/(width*height*a.shape[0])

    return mx.nd.array(sum)  

Upvotes: 1

Divakar
Divakar

Reputation: 221504

Use sum along those three axes and divide by the block size, which would be width*height i.e. a.shape[2]*a.shape[3] -

batch_mean = np.sum(a,axis=(0,2,3))/(a.shape[2]*a.shape[3])

With np.mean(a,axis=(0,2,3)) you were also dividing by the number of elems along the first axis, which doesn't seem to be intended operation there, not at least with sum/(width*height) with your func calc_mean_classic.


Otherwise, if you meant to simulate the behavior of np.mean(a,axis=(0,2,3)) with the loopy calc_mean_classic, just edit the return statement to incorporate a.shape[0] -

return sum, (sum/(width*height*a.shape[0]))

Upvotes: 2

Related Questions