in Games, Machine Learning, Python, Tutorial

Game Barcode: A Study of Colours in Games

This tutorial shows how to download videos from YouTube and to process their frames with Python; I have used this technique to create game barcode, an image created by sorting the colours in each frame of a particular video. You can see some of most intriguing here:

This tutorial is divided in four parts:

Introduction

The idea for this tutorial came to me after reading a post on Reddit titled The average color of every frame of a given movie. I immediately wanted to apply this technique to games. The main reason is that games, compared to movie, have much smoother transitions. This allows to see how colours change very clearly. On top of that, I wanted to explore this concept further, by applying the techniques I’ve discussed in The Incredibly Challenging Task of Sorting Colours. I tested my hypothesis on a short clip from a game I am working on, and the result was quite stunning.

colours_StillTime_600

Another important reason why I wanted to use games rather than movies, is that working with the latter brings you dangerously close to the neutral zone of piracy and copyright infringement. Switching to games, however, you are forced to used a particular Let’s Play video. All the game barcodes in this post have been generated from Let’s Plays I have found on YouTube. I have no affiliation with their respective creators. You can see all the game barcodes here.

GameBarcode: A Study of Colours in Games

Step 1. Processing a video

Let’s start with a top-down approach. Each movie is processed by the process_video function. Frames are extracted using the library OpenCV, then passed through process_frame which returns the list of sorted colours within that frame.

import cv2

def process_video (input_movie, size=(2000,100)):
    colours = []

    # Takes the frames of the video
    cap = cv2.VideoCapture(input_movie)
    while cap.isOpened():
        flag, frame = cap.read()
        if not flag:
            continue

        # Processes the frame
        colours_frame = process_frame(frame, size[1])
        colours.append(colours_frame)
    
    # Generates the final picture
    generate_pic(colours, size)

Finally, all the sorted colours are given to generate_pic which joints them together to create the final picture.

Step 2. Processing a frame

Processing a frame is relatively straightforward. First, the frame is reduced in size to save time and memory. Then, is it reshaped into an array and sorted. For this process I have chosen to sort the colours in the HSV space, since it is more consistent across different frames. In the last step, the sorted array is converted back into an image and interpolated to the requested size using cv2.resize.

import numpy as np
import colorsys

def process_frame (frame, height=100):
    # Resize and put in a single line
    image = resize_image(frame)
    image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
    image = image.reshape((image.shape[0] * image.shape[1], 1, 3))
    
    # Sort the pixels
    sorted_idx = np.lexsort(    (image[:,0,2], image[:,0,1], image[:,0,0]  )   )
    image = image[sorted_idx]

    # Resize into a column
    image_column = cv2.resize(image, (1, height), interpolation=cv2.INTER_AREA)
    return image_column

The function to resize the original frame is this one:

def resize_image (image, size=100):
    # Resize it
    h, w, _ = image.shape
    w_new = int(size * w / max(w, h) )
    h_new = int(size * h / max(w, h) )
     
    image = cv2.resize(image, (w_new, h_new));
    return image

Step 3. Creating the barcode

The final step to create the image is to join all the sorted columns together. We also convert the image back to RGB.

def generate_pic (colours, size):
    # Generates the picture
    height = size[1]
    img = np.zeros((height,len(colours),3), np.uint8)

    # Puts the colours in the image
    for x in range(0, len(colours)):
        for y in range(0, height):
            img[y,x,:] = colours[x][y,0]

    # Converts back to RGB
    img = cv2.cvtColor(img, cv2.COLOR_HSV2RGB)
    cv2.imwrite("barcode_full.png", img)

If you want to resize the image to a more manageable size, you can use this code:

image_1 = cv2.resize(img, size, interpolation=cv2.INTER_AREA)
cv2.imwrite("barcode_%d.png" % size[0], image_1)

Step 4. Downloading from YouTube

Since many Let’s Play are on YouTube, it makes sense to invest some time to download them directly. I have used pafy, a Python library which allows to query YouTube.

# Download the video
video = pafy.new('https://www.youtube.com/watch?v=Re5NFApk9dQ')
resolution = video.getbestvideo(preftype="mp4")
input_movie = resolution.download(quiet=False)

# Process it
process_video(input_movie)
os.remove(input_movie)

If you work is derivative (i.e.: if you are using someone else video), don’t forget to credit them.

Conclusion

If you are curious to see this technique applied to movies, there is a nice selection here.

View post on imgur.com

Other resources

💖 Support this blog

This website exists thanks to the contribution of patrons on Patreon. If you think these posts have either helped or inspired you, please consider supporting this blog.

Patreon Patreon_button
Twitter_logo

YouTube_logo
📧 Stay updated

You will be notified when a new tutorial is released!

📝 Licensing

You are free to use, adapt and build upon this tutorial for your own projects (even commercially) as long as you credit me.

You are not allowed to redistribute the content of this tutorial on other platforms, especially the parts that are only available on Patreon.

If the knowledge you have gained had a significant impact on your project, a mention in the credit would be very appreciated. ❤️🧔🏻

Write a Comment

Comment

Webmentions

  • Something for the weekend #010 | OZARIN

    […] Zucconi shares his colour study techniques in Game Barcode: A Study of Colours in Games. Using Python, Zucconi shows how to output a colour script from a play through video. This is a […]

  • You’re looking at a video game stripped down to its colors, frame-by-frame | RocksGame

    […] all colors into each slice. It sounds complicated, but it's really not. In fact, Zucconi has a tutorial on his website so you can create your own […]