Home computer Soccer World Cup 2018 Average Face by Team

Soccer World Cup 2018 Average Face by Team

Soccer World Cup 2018 Average Face by Team
World Cup 2018 Average Player Face by Team
World Cup 2018 Average Player Face by Team
World Cup 2018 Average Player Face by Team


I thought today while watching England vs. Tunisia that soccer players look very much alike, especially within a team, and so I thought I could compute the average face by soccer team for this world cup.


Getting the data, in this case, images for each player in the current soccer world cup is arguably critical. The images need to have a plain background, similar illumination, and ideally, equal size. Luckily, the FIFA has done all of this, and the images are available online: https://www.fifa.com/worldcup/players/

If you inspect one of the player’s elements, you can access the URL for the player’s image, which can then be downloaded programmatically.

Inspecting the player element on the browser console shows the URL.

I extracted the page’s source code, and downloaded the 736  300 by 300 pixels images corresponding to all players in the world cup (32 teams by 23 player per team = 736).

Averaging a face

Average face is a loosely defined term; a naive implementation could be to treat the images as numerical matrices and use NumPy to average their value. This is only a few lines of code:

import numpy as np
import imageio

countries = ['argentina', 'belgium', 'colombia', 'croatia', ...]

for country in countries:
    images_stacked = np.zeros((23, 300, 300, 3))

    for i in range(0, 23):
        images_stacked[i] = imageio.imread('images-input/%s/%s_%s.jpg' % (country, country, i))

    results = np.zeros((300, 300, 3))

    for color in range(0, images_stacked.shape[3]):
        for x_pos in range(0, images_stacked.shape[1]):
            for y_pos in range(0, images_stacked.shape[2]):
                results[x_pos, y_pos, color] = np.mean(images_stacked[:, x_pos, y_pos, color])

    imageio.imwrite('images-output/%s_naive_averager.png' % country, results)

There is room for improving on this code, but I am  not interested in that, rather on the actual results. And here is how they show:

Sweden Naive Average Face

Let’s look at another example:

Brazil Naive Average Face

Even though images are standard, averaging the pixel values doesn’t build a compelling picture; sure, we can distinguish some features such as color of the t-shirt or hair, but we can’t “put a face to it”. We need to think of something else…

Face morpher

Of course there is a better way,  meet Face Morpher (FM from now own). FM works in a different way to find the average face, instead of averaging the pixel values, it builds a geometry of the face by identifying elements on it, such as the eyes or cheeks. It then proceeds to average those sections across images.

The results are much more compelling, and we are definitely able to put a face to this teams now.

Sweden FM Average Face

Or in the case of Brazil:

Brazil FM Average Face

It looks great! And yet, aren’t we missing important and distinctive elements, such as the hair, ears, or even team t-shirt?

Face art

I decided to them combine the two images: naive + FM for a more compelling result. I blended the images using Sketch, the naive average serves as background, and overlayed on top a semi-transparent FM face.

Quite happy with the result:

World Cup 2018 Average Player Face by Team
World Cup 2018 Average Player Face by Team


How does the average face look across all countries then?

Average face across all countries
Average face across all countries

Congratulations to France ???????? on this World Cup, and hope you had fun watching the games and reading through this visualization.  Comment if you like!