Question: I have found a working code for this, but don't understand everything about these lines:

```
counter = np.unique(img.reshape(-1, img.shape[2]), axis=0)
print(counter.shape[0])

```

Especially these values:

```
-1, img.shape[2], axis=0

```

What does that -1 do, why is the shape 2, and why is axis 0?
And after that, why do we print shape[0]?

Answer: 
If you don't understand a complex sentence, always break them up and print shapes.

```
print(img.shape)
img2 = img.reshape(-1, img.shape[2]) # reshape the original image into -1, 3; -1 is placeholder, so lets say you have a 
                                     # numpy array with shape (6,2), if you reshape it to (-1, 3), we know the second dim = 3
                                     # first dim = (6*2)/3 = 4, so -1 is replaced with 4
print(img2.shape)

counter = np.unique(img2, axis=0) # find unique elemenst
'''
numpy.unique(ar, return_index=False, return_inverse=False, return_counts=False, axis=None)[source]
Find the unique elements of an array.

Returns the sorted unique elements of an array. There are three optional outputs in addition to the unique elements:

the indices of the input array that give the unique values
the indices of the unique array that reconstruct the input array
the number of times each unique value comes up in the input array
'''
print(counter)
print(counter.shape) # as, we have separate axis, so the channels are shown in dim 2
print(counter.shape[0])

```

But, this one is probably not correct as it doesn't consider unique RGB across channel.

So, the following is a better one, you flatten the array to get a list then using set find the unique elements and finally print the len of the set.

A handy shortcut is ->

```
print(len(set(img.flatten())))

```
It is calculating the number of unique RGB pixel values in the image. In other word it is calculation the number of different colors in the images

`img.reshape(-1, img.shape[2])` : A three channel image flattened per channel. A 3 channel image is of shape `width x height x 3` where each channels (3 here) corresponds to RGB or BGR depending on how you read the image. We are reshaping it into 2 dimensions, RGB values per channel. So second dimension will be number of channels. so if you know the width and height of image, it is equal to `img.reshape(w*h, img.shape[2])` which is same as `img.rehape(img.shape[0]*img.shape[1], img.shape[2])`. Intutively think of it like you are taking a 3 channel image and laying out the colors of pixels one after the other. In numpy you can always leave out one dimension as -1 which is automatically calculated based on the shape of the object and the other dimensions. 

Now that we have layed out pixes one after the other we can calculate the number of unique colors, but since color is represented by 3 (RGB) values we want to calculated unique RGB values which is done by using `np.unique` over the second dimension which is channel. This returns all the unique RGB values, which will be of size `n x 3` where n are the unique pixel values. Finally since we want to find the count, `shape` will return `(n,3)` we select `shape[0]` which will return `n`.

Code
====

```
# image of size 200 X 200 X 3 => 200 pixels width 200 pixels height => total 200*200 pixels 
img = np.random.randint(0,256, (200,200,3))
print (img.shape)
# Flatten the image to 200*200 pixels
img = img.reshape(-1, img.shape[2])
print (img.shape)
# Count unique colors
counter = np.unique(img, axis=0)
# n unique colors (3 values per pixel)
print (counter.shape)

```

Output

```
(200, 200, 3)
(40000, 3)
(39942, 3)

```