Fragments

An embarrassing position

A raccoon society tryptich


Yesterday, the raccoon society met once again, for the purposes of digging through trash and collaging it into some art.

After the placing of our ceremonial raccoon, Matt and I got to work on a triptych each.

Here's mine. I'm calling it An embarrassing position

And here are the individual panels in closer detail

Fancies of an upside-down world


Then came The Wheel of Fortune at the very moment when we were expecting a more detailed description of the world of the Moon, which would allow us to indulge in the old fancies of an upside-down world, where the ass is king, man is four-legged, the young rule the old, sleepwalkers hold the rudder, citizens spin like squirrels in their cage's wheel, and there are as many other paradoxes as the imagination can disjoin and join.

-Italo Calvino, The Castle of Crossed Destines
translated by William Weaver

Untitled inbox collage #1

A week of internet content, newsletters, and notifications


From the past week of my inbox.

How I made this

First, I took screenshots of emails and newsletter content, as well as some other bits and bobs:

Then I wrote a python script to separate text from background in a particular image

import cv2
import numpy as np
import os
import argparse

def split_text_background(image_path, output_dir):
  os.makedirs(output_dir, exist_ok=True)

  image = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)

  if image is None:
      print(f"Error: Could not open image at {image_path}")
      return

  if image.shape[2] == 3:  # If only BGR channels exist
      image = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)

  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

  _, text_mask = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)

  text_only = np.zeros_like(image, dtype=np.uint8)
  text_only[:, :, 0:3] = image[:, :, 0:3]
  text_only[:, :, 3] = text_mask

  background_only = image.copy()
  background_only[:, :, 3] = cv2.bitwise_not(text_mask)

  base_name = os.path.splitext(os.path.basename(image_path))[0]
  background_output_path = os.path.join(output_dir, f"{base_name}_background.png") 
  text_output_path = os.path.join(output_dir, f"{base_name}_text.png") 

  cv2.imwrite(background_output_path, background_only)
  cv2.imwrite(text_output_path, text_only)

  print(f"✅ Background extracted and saved to: {background_output_path}")
  print(f"✅ Text extracted and saved to: {text_output_path}")

if __name__ == "__main__":
  parser = argparse.ArgumentParser(description="Split text and background from an image while preserving transparency.")
  parser.add_argument("image_path", help="Path to the input image")
  parser.add_argument("-o", "--output", default=".", help="Output directory (default: current directory)")

  args = parser.parse_args()

  split_text_background(args.image_path, args.output)

After creating these text masks the hard way, I got to work in Figma stitching it all together.

Mockus and the traffic mimes

A delightful social experiment in Bogotá


In Bogotá, a delightful contrast to the fascistic authoritarianism that is so prevalent now. I love the playfulness of this, the artistry of it, the implicit argument that a state does not need violence (or the threat thereof) to encourage people to behave differently. More traffic mimes and fewer traffic cops, please!