Skip to content

Instantly share code, notes, and snippets.

@raymag
Created March 17, 2024 03:38
Show Gist options
  • Save raymag/c42730306c5357dddc2defa50f4a1b50 to your computer and use it in GitHub Desktop.
Save raymag/c42730306c5357dddc2defa50f4a1b50 to your computer and use it in GitHub Desktop.
Transforms video from webcam into a real-time ascii art
import math
import cv2 as cv
import numpy as np
import sys
import pygame
gscale1 = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"`'. "[::-1]
thresholds = [x * 5 for x in range(70)]
def get_ascii_from_frame(frame):
img = frame
height, width = img.shape
max_height = 100
h = height
if height >= max_height:
h = max_height
ratio = height // max_height
w = width // ratio
else:
w = width // (width // height)
img = cv.resize(img, (int(w), int(h)), interpolation=cv.INTER_CUBIC)
thresh_img = np.zeros(img.shape)
for i, threshold in enumerate(thresholds):
thresh_img[img > threshold] = i
thresh_img = thresh_img.astype(int)
art = []
for row in thresh_img:
art_row = []
for i in row:
art_row.append(gscale1[i % len(gscale1)])
art.append(art_row)
return art
pygame.init()
screen = pygame.display.set_mode((1280, 720))
clock = pygame.time.Clock()
def map_to_range(val, lmin, lmax, rmin, rmax):
return rmin + ((rmax - rmin) / (lmax - lmin)) * (val - lmin)
def get_color():
time = pygame.time.get_ticks()
booster = 0.001
r = map_to_range(math.sin(time * booster), -1, 1, 0, 255)
g = map_to_range(math.sin(time * booster + 4), -1, 1, 0, 255)
b = map_to_range(math.sin(time * booster + 8), -1, 1, 0, 255)
return (r, g, b)
def render_ascii(frame=None):
frame = get_ascii_from_frame(frame)
img = list(zip(*frame[::-1]))
size = 6
for i, row in enumerate(img):
for j, col in enumerate(row[::-1]):
char = font.render(col, True, (255, 255, 255))
screen.blit(char, (i * size, j * size))
font = pygame.font.Font(None, 20)
cap = cv.VideoCapture(0)
if not cap.isOpened():
print("Can't open cam")
exit()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
screen.fill((20, 20, 30))
ret, frame = cap.read()
if not ret:
print("Can't read frame")
break
frame = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
render_ascii(frame)
pygame.display.update()
clock.tick(60)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment