Building a Python QR Scanner to Generate Characters

Jon-luke Diericks
4 min readAug 17, 2023

--

I’ve always imagined a world where QR codes and barcodes hold the key to unlocking unique characters and items — think Digimon. In this article, I’ll guide you through the building a Python-based QR code scanner that generates character data. Not only will you learn how to create this simple application, but you’ll also gain insights into best practices for coding and data manipulation.

What are we building?

We’re making a Python app that can scan QR codes using your computer’s camera. Once it scans a QR code, it will change the data from the code into a format called JSON. This JSON will have all the details about our character.

Whet You Need

Before we begin, you need to have Python installed on your computer, and your computer should have a camera. We’ll use three helpful packages: opencv-python, pyzbar and hashlib. If you’re using a Macbook M1, you’ll need to install an extra package called zbar.

Let’s Get This Party Started!

#First we import our tools
import cv2
from pyzbar.pyzbar import decode
import hashlib

#Inits webcam
cap = cv2.VideoCapture(0)

#Set camera screen dimensions
cap.set(3,640)
cap.set(4,480)

#Init QR Code Detector
detector = cv2.QRCodeDetector()

We’re all set up! We’ve got the tools we need and our camera is ready to go.

How It All Works

#Running the main app
while True:
#Grab a frame from the camera
ret, frame = cap.read()

#If we can't get a frame, somethings wrong
if not ret:
print("Error capturing video frame")
break

#Detect and decode the QR Code in the frame
data, box, qrcode = detector.detectAndDecode(frame)

#Lets play with the QR Code we find
for barcode in decode(frame):

code_data = barcode.data.decode('utf-8')

#Stripping our some data - makes the character data less predictable
code_data = code_data.replace("https://", "")
code_data = code_data.replace("http://", "")
code_data = code_data.replace("www.", "")
code_data = code_data.replace(".org", "")
code_data = code_data.replace(".com", "")
code_data = code_data.replace("/", "")

#Run our create_character function
character = create_character(code_data)

print(character)

#Display the character info on top of the camera screen
pts = np.array([barcode.polygon],np.int32)
pts = pts.reshape((-1,1,2))
cv2.polylines(frame,[pts],True,(255,0,255),5)

y0, dy = 50, 30
for i, (key, val) in enumerate(character.items()):
y = y0 + i * dy
cv2.putText(frame, f'{key}: {val}', (50, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)

#Display the frame
cv2.imshow('frame', frame)

if cv2.waitKey(1) & 0xFF == ord('q'):
break

#When everything is done, relase the capture
cap.release()
cv2.destroyAllWindows()

We’re capturing frames from the camera, finding QR codes in them, and changing the QR code data into a character.

Sample of the data that has been captured and processed
#This function makes our characters
def create_character(data):
#Checking if data is empty
if len(data) == 0:
return None

#Generate an id or "gene_code" to create our character data
gene_code = hashlib.sha256((data + "mediumArticle2023").encode()).hexdigest()

#Break the id into an array of numbers
numbers = [ord(char) for char in gene_code]

print(gene_code)
print(numbers)

#Generating the individual character attributes based on the numbers array data
if 48 <= numbers[0] <= 57: # ASCII values for 0-9
char_type = "Human"
elif 58 <= numbers[0] <= 64: # ASCII values for : - @
char_type = "Demi-Human"
elif 65 <= numbers[0] <= 90: # ASCII values for A-Z
char_type = "Insect"
elif 91 <= numbers[0] <= 96: # ASCII values for [ - `
char_type = "Mythical Beast"
else: # ASCII values for a-z and above
char_type = "slime"

if numbers[1] < 50:
rarity = "Legendary"
elif 50 <= numbers[1] < 75:
rarity = "Rare"
elif 75 <= numbers[1] < 90:
rarity = "Uncommon"
else: # 90 and above
rarity = "Common"

if numbers[10] < 50:
gender = "Male"
else: # 90 and above
gender = "Female"

if numbers[1] < 10:
attribute = "Holy"
elif 10 <= numbers[1] < 25:
attribute = "Dark"
elif 25 <= numbers[1] < 40:
attribute = "Light"
elif 40 <= numbers[1] < 70:
attribute = "Fire"
elif 70 <= numbers[1] < 90:
attribute = "Water"
else: # 90 and above
attribute = "None"

character = {
'gene_code': gene_code,
'type': char_type,
'rarity': rarity,
'gender': gender,
'element': attribute,
'health': numbers[3] if len(numbers) > 3 else 0,
'intelligence': numbers[4] if len(numbers) > 4 else 0,
'strength': numbers[5] if len(numbers) > 5 else 0,
'stamina': numbers[6] if len(numbers) > 6 else 0,
'agility': numbers[7] if len(numbers) > 7 else 0,
'defense': numbers[8] if len(numbers) > 8 else 0,
'chrisma': numbers[9] if len(numbers) > 9 else 0,
}

return character
Character data that is displayed from our application; type: Human, rarity: Common, gender: Female, element: None, health: 101, intelligence: 48, strength: 51, stamina: 100, agility: 53, defense: 51, charisma: 102
Example of the character data being displayed on the screen

Our create_character function acts like a character factory. It takes the QR code data, scrambles it a bit, and creates a unique character with special traits.

Future Articles and Updates

In a following article I will show how to turn this application into an API to use with modern web applications. I will also have an article about building an iOS application to work with this API. Stay Tuned!

Planned updates for this project

— Build a custom image generating AI to generate character profile images.

Thats all Folks!

TL;DR — A Python-based application to scan QR codes and generate character data.

--

--

Jon-luke Diericks

Passionate about Python and creating interesting projects. I am a self-taught full-stack developer currently working in the field as a front-end developer.