Creating Blurred Images for a Hindsight Bias Demonstration

R
teaching
psychology
Using R to generate progressively revealed images for teaching about hindsight bias.
Published

January 15, 2024

I use a visual hindsight bias demonstration in class where students watch a blurry image gradually come into focus and try to identify who it is. After the reveal, I ask when they first recognized the person. Most students are convinced they knew way earlier than they actually did—which is a nice setup for talking about hindsight bias and why it matters for things like eyewitness memory and legal decision-making.

I wanted a quick way to generate these stimuli in R rather than fiddling around in Photoshop, so I put together a couple of functions using the magick package. Most of this is adapted from a Stack Overflow answer I found when I was trying to figure out how to make the GIF.

The Packages

Nothing fancy here—magick does the image processing, here keeps the file paths sane, and gifski compiles the frames into a GIF.

library(magick)
library(here)
library(gifski)

The Functions

A series of stills

This first function takes an image and creates a series of progressively less blurry versions. The blur starts at maximum and decreases linearly, so the first image is almost unrecognizable and the last one is the original.

create_blurred <- function(image_path, output_dir, prefix = "blurred", num_images = 6) {
  original <- image_read(image_path)
  max_blur <- 99.9999
  
  for (i in 1:num_images) {
    blur_amount <- max_blur * (1 - (i - 1) / (num_images - 1))
    blurred <- image_blur(original, radius = blur_amount, sigma = blur_amount / 2)
    image_write(blurred, path = file.path(output_dir, sprintf("%s_%d.png", prefix, i)))
  }
}

An animated GIF

If you want to compile everything into a GIF for presentations, this version handles both steps. I use more frames here (30 instead of 6) so the animation feels smoother.

create_blurred_and_gif <- function(image_path, output_dir, prefix = "blurred", 
                                    num_images = 30, width = 800, height = 600, delay = 0.5) {
  original <- image_read(image_path)
  max_blur <- 99.9999
  
  png_paths <- vector("character", num_images)
  for (i in 1:num_images) {
    blur_amount <- max_blur * (1 - (i - 1) / (num_images - 1))
    blurred <- image_blur(original, radius = blur_amount, sigma = blur_amount / 2)
    png_path <- file.path(output_dir, sprintf("%s_%02d.png", prefix, i))
    png_paths[i] <- png_path
    image_write(blurred, path = png_path)
  }
  
  gif_path <- file.path(output_dir, sprintf("%s_images.gif", prefix))
  gifski(png_files = png_paths, gif_file = gif_path, width = width, height = height, delay = delay)
  
  return(gif_path)
}

Generating the Stimuli

Set eval: true the first time you render to create the images, then set it back to eval: false so they don’t get regenerated on every render.

output_dir <- here("posts", "hindsight-visual")

# Meryl Streep - 6 stills for the grid, 30 frames for the GIF
create_blurred(
  image_path = here("posts", "hindsight-visual", "meryl_streep.png"),
  output_dir = output_dir,
  prefix = "meryl",
  num_images = 6
)

create_blurred_and_gif(
  image_path = here("posts", "hindsight-visual", "meryl_streep.png"),
  output_dir = output_dir,
  prefix = "meryl",
  num_images = 30,
  width = 800,
  height = 600,
  delay = 0.5
)

# Jeff Probst - slower reveal, smaller dimensions
create_blurred(
  image_path = here("posts", "hindsight-visual", "jeff_probst.png"),
  output_dir = output_dir,
  prefix = "jeff",
  num_images = 6
)

create_blurred_and_gif(
  image_path = here("posts", "hindsight-visual", "jeff_probst.png"),
  output_dir = output_dir,
  prefix = "jeff",
  num_images = 40,
  width = 600,
  height = 450,
  delay = 0.7
)

What You Get

Meryl Streep

Here’s the progression as a series of stills:

And the animated version:

Jeff Probst

Same idea, but with a slower reveal:

How I Use This

I can run the visual hindsight bias demonstration using the embedded GIF and create new ones to keep up with the kids as my pop cultural references age.

Back to top