Skip to content

Instantly share code, notes, and snippets.

@Ivorforce
Created July 5, 2024 20:55
Show Gist options
  • Save Ivorforce/97c19daa2bd4075af5179d3bf96ebebd to your computer and use it in GitHub Desktop.
Save Ivorforce/97c19daa2bd4075af5179d3bf96ebebd to your computer and use it in GitHub Desktop.
import PIL.Image
import numpy as np
import matplotlib.pyplot as plt
from einops import rearrange, reduce, repeat
import cv2
#############################################################################################
ascii = PIL.Image.open('../resources/8s0Sj.gif')
ascii = np.asarray(ascii) * 16
ascii = rearrange(ascii, '(w1 w2) (h1 h2) -> (w1 h1) w2 h2', w2=16, h2=16)
plt.imshow(ascii[64 + 16 * 2 + 1])
ascii_pad = np.pad(ascii[64 + 16 * 2 + 1], ((16, 16), (16, 16)), 'constant', constant_values=0)
coords = np.mgrid[:48, :48].transpose((1, 2, 0)).reshape((-1, 2))
ascii_flat = ascii_pad.reshape(-1)
coords = coords[ascii_flat > 0]
x_min = np.min(coords[:, 0])
x_max = np.max(coords[:, 0]) + 1
y_min = np.min(coords[:, 1])
y_max = np.max(coords[:, 1]) + 1
char_width = x_max - x_min
char_height = y_max - y_min
ascii = []
for shift_x in range(x_min - (16 - char_width), x_min):
for shift_y in range(y_min - (16 - char_height), y_min):
ascii.append(ascii_pad[shift_x:shift_x + 16, shift_y:shift_y + 16])
ascii = np.array(ascii)
#############################################################################################
capture = cv2.VideoCapture("/Users/lukas/Downloads/bad_apple.mp4")
width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = capture.get(cv2.CAP_PROP_FPS)
print(width, height, fps)
out = cv2.VideoWriter()
if not out.open('output.mov', cv2.VideoWriter_fourcc(*'mp4v'), fps, (width, height), False):
raise IOError()
try:
while capture.isOpened():
ret, img_src = capture.read()
if not ret:
break
img = img_src
# Resolution fix
img = img[:height // 16 * 16, :width // 16 * 16]
img = img[:, :, 0] * 0.299 + img[:, :, 1] * 0.587 + img[:, :, 2] * 0.114
img = rearrange(img, '(w1 w2) (h1 h2) -> (w1 h1) w2 h2', w2=16, h2=16)
diff = np.mean((img[:, None] - ascii[None, :]) ** 2, axis=(-2, -1))
idxs = np.argmin(diff, axis=-1)
img_ascii = np.empty_like(img)
for i in range(img.shape[0]):
img_ascii[i] = ascii[idxs[i]]
img_ascii = rearrange(img_ascii, '(w1 h1) w2 h2 -> (w1 w2) (h1 h2)', h1=width // 16)
if img_ascii.shape[-2] < height or img_ascii.shape[-1] < width:
img_ascii = np.pad(img_ascii, ((0, height - img_ascii.shape[-2]), (0, width - img_ascii.shape[-1])), 'constant', constant_values=0)
out.write(img_ascii.astype(np.uint8))
finally:
capture.release()
out.release()
cv2.destroyAllWindows()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment