Reputation: 91
I am creating a sign language detection application in Armenian. However, the Armenian letters don't show when I am signing but do show in my console/terminal. What am I doing wrong with my code that is not working. Let me know how can I change or implement to show the letter on the screen. Currently any non-ascii characters display as ?????
or boxes instead of the actual character or symbol like this
How do I show non-ascii characters/text instead of ??
using OpenCV's putText()
method?
PS: I even try implementing using PIL but no luck. Thanks for your help in advance.
Also, when I use unicode_font instead of cv2.QT_FONT_NORMAL
I get an error when I sign as:
Argument 'fontFace' is required to be an integer
Here is my code:
dict_letter = {0: 'Ա', 1: 'Բ', 2: 'Գ', 3: 'Դ', 4: 'Ե', 5: 'Զ', 6: 'Է', 7: 'Ը', 8: 'Թ', 9: 'Ժ', 10: 'Ի', 11: 'Լ', 12: 'Խ', 13: 'Ծ', 14: 'Կ', 15: 'Հ', 16: 'Ձ', 17: 'Ղ', 18: 'Ճ', 19: 'Մ', 20: 'Յ', 21: 'Ն', 22: 'Շ', 23: 'Ո', 24: 'Չ', 25: 'Պ', 26: 'Ջ', 27: 'Ռ', 28: 'Ս', 29: 'Վ', 30: 'Տ', 31: 'Ր', 32: 'Ց', 33: 'Փ', 34: 'Ք', 35: 'Ֆ'}
font_size=36
unicode_font = ImageFont.truetype("/NEW/NotoSansArmenian-VariableFont_wdth,wght.ttf", font_size)
img = cv2.putText(image_hand, f"{dict_letter[pred]}", (x_square, y_square - 5), cv2.QT_FONT_NORMAL, 0.6, (0,0,0), 2)
Updated code:
image = np.zeros((100, 950, 3), dtype=np.uint8)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
pil_image = Image.fromarray(image)
#using mac
font = ImageFont.truetype("/System/Library/Fonts/Supplemental/Arial.ttf", 35)
draw = ImageDraw.Draw(pil_image)
draw.text((30, 30), dict_letter[pred], font=font)
image = np.asarray(pil_image)
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
cv2.imshow('image', image)
cv2.waitKey()
Upvotes: 9
Views: 10372
Reputation: 46670
To my knowledge, cv2.putText()
only supports a small ascii
subset of characters and not unicode
, utf
, or non-ascii
characters. The short answer is that there's no built-in OpenCV functionality to display unicode
characters/text symbols onto an image. But there's a workaround! We can convert the image from OpenCV to PIL, draw the non-ascii
text onto the image, and then convert back to OpenCV. It's important to remember that OpenCV uses BGR
while PIL uses RGB
so we need to convert from BGR
to RGB
(OpenCV ->
PIL) and RGB
back to BGR
(PIL ->
OpenCV).
The idea is to create a blank mask using Numpy (or any loaded image), convert from OpenCV to PIL, draw non-ascii text onto the image, and then convert from PIL back to OpenCV. Here's a working example displaying each of the Armenian letters:
from PIL import ImageFont, ImageDraw, Image
import cv2
import numpy as np
# Create black mask using Numpy and convert from BGR (OpenCV) to RGB (PIL)
# image = cv2.imread('1.png') # If you were using an actual image
image = np.zeros((100, 950, 3), dtype=np.uint8)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
pil_image = Image.fromarray(image)
# Draw non-ascii text onto image
font = ImageFont.truetype("C:\Windows\Fonts\\arial.ttf", 35)
draw = ImageDraw.Draw(pil_image)
draw.text((30, 30), "ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՓՔՖ", font=font)
# Convert back to Numpy array and switch back from RGB to BGR
image = np.asarray(pil_image)
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
cv2.imshow('image', image)
cv2.waitKey()
Displaying other languages and/or character symbols
Depending on the language/symbol to display, you may have to modify the ImageFont.truetype()
font. On Windows, all of the default fonts are located in the C:\Windows\Fonts
folder. Simply select the desired font depending on the symbol you are trying to display. Right click the font file and select properties to get the exact filename and extension. For example to display Chinese characters:
font = ImageFont.truetype("C:\Windows\Fonts\simsun.ttc", 35)
draw.text((30, 30), "我是你的爸爸", font=font)
For Japanese:
font = ImageFont.truetype("C:\Windows\Fonts\YuGothL.ttc", 35)
draw.text((30, 30), "桜はかっこいい", font=font)
Note: If you're using a Mac, see Loading fonts in Python/Pillow on a Mac
Upvotes: 7