In this post we will discuss how to convert live video broadcast to ascii art using python
Installing Required Packages
pip install opencv-python
pip install pillow
pip install numpy
Code Explanation
import cv2
from PIL import Image,ImageDraw, ImageFont
import math
import numpy
Lets import the required packages packages first
chars = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. "[::-1]
video_capture = cv2.VideoCapture(0)
charArray = list(chars)
charLength = len(charArray)
interval = charLength/256
scaleFactor = 0.09
oneCharWidth = 10
oneCharHeight = 18
chars variable is the string having all the ascii characters, video_capture will capture video stream from webcam you can also take input from various other sources (like mobile phone, wireless arduino camera), charArray will convert string with all ascii character to a list, charlength is the length of all the characters list, oneCharHeight & oneCharwidth is the height and width of one pixel
fnt = ImageFont.truetype('C:\\Windows\\Fonts\\lucon.ttf', 15)
fnt will be font of characters on our ascii art
while True:
_,im = video_capture.read()
im= cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
color_coverted = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
im = Image.fromarray(color_coverted)
width, height = im.size
im = im.resize((int(scaleFactor*width), int(scaleFactor*height(oneCharWidth/oneCharHeight))), Image.NEAREST)
width, height = im.size
pix = im.load()
Inside an infinite we will read our incoming video and store it in im variable , for better feature recognition we will convert our rgb image to black and white, by using fromarray we will convert array to image for pillow image manipulation , resize function will resize the image according to our parameters, pix will be the variable that loads or image
outputImage = Image.new('RGB', (oneCharWidth * width, oneCharHeight * height), color = (0, 0, 0))
d = ImageDraw.Draw(outputImage)
for i in range(height):
for j in range(width):
r, g, b = pix[j, i]
h = int(r/3 + g/3 + b/3)
pix[j, i] = (h, h, h)
d.text((j*oneCharWidth, i*oneCharHeight), getChar(h), font = fnt, fill = (r, g, b))
outputImage will create a new blank image that we will use to write our ascii characters on, d is class instance we will use to draw ascii characters, after that we will create two while loop for both row and column to access each pixel , r,g & b are variables that will store red green and blue values of each pixel after that we will select ascii characters for each of theses ascii bundles and write on blank image
outputImage = numpy.array(outputImage)
outputImage = outputImage[:, :, ::-1].copy()
cv2.imshow("attendence system",outputImage)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
cv2.destroyAllWindows()
final task is to display the output to the user and close all windows
watch this tutorial for more detailed explanation
Complete Code
import cv2
from PIL import Image,ImageDraw, ImageFont
import math
import numpy
chars = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. "[::-1]
video_capture = cv2.VideoCapture(0)
charArray = list(chars)
charLength = len(charArray)
interval = charLength/256
scaleFactor = 0.09
oneCharWidth = 10
oneCharHeight = 18
def getChar(inputInt):
return charArray[math.floor(inputInt*interval)]
fnt = ImageFont.truetype('C:\\Windows\\Fonts\\lucon.ttf', 15)
while True:
_,im = video_capture.read()
im= cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
color_coverted = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
im = Image.fromarray(color_coverted)
width, height = im.size
im = im.resize((int(scaleFactor*width), int(scaleFactor*height*(oneCharWidth/oneCharHeight))), Image.NEAREST)
width, height = im.size
pix = im.load()
outputImage = Image.new('RGB', (oneCharWidth * width, oneCharHeight * height), color = (0, 0, 0))
d = ImageDraw.Draw(outputImage)
for i in range(height):
for j in range(width):
r, g, b = pix[j, i]
h = int(r/3 + g/3 + b/3)
pix[j, i] = (h, h, h)
d.text((j*oneCharWidth, i*oneCharHeight), getChar(h), font = fnt, fill = (r, g, b))
outputImage = numpy.array(outputImage)
outputImage = outputImage[:, :, ::-1].copy()
cv2.imshow("attendence system",outputImage)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
cv2.destroyAllWindows()