Barcode Remix
A circular take on the movie barcode

a

Preface

Visualizing data can often be a rather serious affair. Typically in the business world it involves well labeled axes, approved color palletes, and just a handful of chart types. While such rigor isn't necissarliy a bad thing, sometimes it's nice to be remined that visualizing data can be just as artistic as it is scientifc. The movie barcode is just that, an artistic data visualization that takes a failry large amount of image data and represents it in an intuitive (and colorful) way.

In this project, I create a circular movie barcode for S1 E1 of the show 24. The final product showcases the average color of 2,400 sequential scenes from the episode.

Image Extraction

There are a variety of ways to extract still images from media stored locally, but options are somewhat limited for streaming media (as was the case here). To accomplish this task I decided to let the episode play through on a second monitor and automate the screen capture process with Python's Pillow library. The loop below is all that was required to focus on the region of the screen that contained the video, take a screenshot every second, and save the images locally with chronological labels.

from PIL import ImageGrab

#take a screen shot every 1s and save image w/ timestamp
while(True):
    img = ImageGrab.grab(bbox=(45,190,430,410)) # bbox = x,y,width,height
    timestamp = strftime("%H_%M_%S", gmtime())
    img.save(timestamp+'.bmp')
    sleep(1)

Image Processing

Now that we have our collection of frames saved as .bmp images, I'll use R's bmp library to process the images and prepare them for plotting. There are a variety of methods to process image data but I've taken the simple approach of averaging the red, green and blue values in each image and saving the resulting "mean" RGB color code. I'll make a quick density plot of the component colors to check the distribution of these values.

#extract RGB from images in working directory and record mean values in dataframe
image_list <- list()
for(idx in seq_along(list.files())) {

  image <- read.bmp(list.files()[idx])
  image_list[[idx]] <- data.frame(red = round(mean(image[,,1]),0),
                                  green = round(mean(image[,,2]),0),
                                  blue = round(mean(image[,,3]),0))
}
image_df <- bind_rows(image_list)

Image Processing cont.

A reasonable looking density plot. Looks like each color is distributed somewhat normally with all component values skewing darker (closer to zero) which is to be expected. On to the main event!

For the barcode plot we will need to covert the RGB values to hex codes and create a custom color pallette to fill in the bars that will be generated for each frame. we'll then genreate two plots - a standard rectangular barcode, and a circular barcode using ggplot's built in polar coordinate system.

#convert rgb to hex & add row number for x-axis ordering
image_df2 <- image_df %>%
  mutate(hex = rgb(red/255,green/255,blue/255),
         row_num = row_number())

#create hex lookup array for plotting
col <- as.character(image_df2$hex)
names(col) <- as.character(image_df2$hex)

#plot barcode
plot <- image_df2 %>%
  ggplot(aes(x = row_num, y = 1, fill = hex, color = hex))+
  geom_col()+
  scale_fill_manual(values = col) +
  scale_color_manual(values = col) +
  guides(color=F,fill=F) +
  theme_void()

#plot circular barcode using polar coordinates
plot2 <- plot + coord_polar()

Post Processing

Well we can't stop yet, this is an art project after all. It's time to import these barcodes into a vector graphics editor and get a little creative. I'm using Inkscape but I'm sure similar results could be achieved in Illustrator or something else. After playing around a little bit I decided to create a circular clock-inspired object with 24 imposed in the middle. I think this could be even more appropriate (and cool) if it featured all 24 episodes of season 1 in their corresponding clock positions.. certainly an idea for next time!