Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Convert image to ascii art
import sys; from PIL import Image; import numpy as np
chars = np.asarray(list(' .,:;irsXA253hMHGS#9B&@'))
if len(sys.argv) != 4: print( 'Usage: ./ image scale factor' ); sys.exit()
f, SC, GCF, WCF = sys.argv[1], float(sys.argv[2]), float(sys.argv[3]), 7/4
img =
S = ( round(img.size[0]*SC*WCF), round(img.size[1]*SC) )
img = np.sum( np.asarray( img.resize(S) ), axis=2)
img -= img.min()
img = (1.0 - img/img.max())**GCF*(chars.size-1)
print( "\n".join( ("".join(r) for r in chars[img.astype(int)]) ) )

This comment has been minimized.

Copy link

@codedude codedude commented Jun 16, 2016

Thanks, it works great ;)


This comment has been minimized.

Copy link

@stratosgear stratosgear commented Nov 16, 2016


This comment has been minimized.

Copy link

@piotrusin piotrusin commented Nov 18, 2017



This comment has been minimized.

Copy link

@Schizo Schizo commented Nov 29, 2017

you can do all one line when you fill it up with ;


This comment has been minimized.

Copy link

@HughJazz123 HughJazz123 commented Jun 4, 2019

Sorry, I'm kinda new to this, but how do you exactly make this work while you're running it?


This comment has been minimized.

Copy link

@MikeTheWatchGuy MikeTheWatchGuy commented Aug 14, 2019

OMG Thank you for this!!!!!

I was able to use it with my GUI package and run it in a GUI window (tkinter based) and changed a line of code and ran it in a Browser (Remi based). And, it was trivial to add in your code. It was all done in 25 lines of code thanks your magic! Thank you!!!

Here's the PySimpleGUI one (tkinter)


Here's the PySimpleGUIWeb version

ASCII Movie Web

Sorry that I hacked up your code a bit, but it wasn't THAT bad.

Can I put the code here? I'll move it if asked. Just don't want to fart around with a Gist and it does show one way of integrating your code into something bigger perhaps

from PIL import Image; import numpy as np
import PySimpleGUI as sg
import cv2

# The magic bits that make the ASCII stuff work shamelessly taken from
chars = np.asarray(list(' .,:;irsXA253hMHGS#9B&@'))
SC, GCF, WCF = .1, 1, 7/4

sg.ChangeLookAndFeel('Black')   # make it look cool

# define the window layout
NUM_LINES = 48  # number of lines of text elements. Depends on cameras image size and the variable SC (scaller)
layout =  [*[[sg.T(i, size=(115,1), font=('Courier', 12), key='_OUT_'+str(i))] for i in range(NUM_LINES)],
          [ sg.Button('Exit')]]

# create the window and show it without the plot
window = sg.Window('Demo Application - OpenCV Integration', layout, location=(800,400),
                   no_titlebar=True, grab_anywhere=True, element_padding=(0,0))

# ---===--- Event LOOP Read and display frames, operate the GUI --- #
cap = cv2.VideoCapture(0)                               # Setup the OpenCV capture device (webcam)
while True:
    event, values = window.Read(timeout=0)
    if event in ('Exit', None):
    ret, frame =                             # Read image from capture device (camera)

    img = Image.fromarray(frame)  # create PIL image from frame
    # More magic that coverts the image to ascii
    S = (round(img.size[0] * SC * WCF), round(img.size[1] * SC))
    img = np.sum(np.asarray(img.resize(S)), axis=2)
    img -= img.min()
    img = (1.0 - img / img.max()) ** GCF * (chars.size - 1)

    # "Draw" the image in the window, one line of text at a time!
    for i, r in enumerate(chars[img.astype(int)]):
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.