بلاگ

فارسی نویسی توی OopenCV پایتون - UTF-8 in opencv python

فارسی نویسی توی OopenCV پایتون - UTF-8 in opencv python

در این پست یک راه حل نسبتا ساده برای نوشتن فارسی نویسی موقع استفاده از OpenCV رو بررسی میکنیم.

 

openCV چیست؟

اوپن‌سی‌وی یا همان Open Computer Vision Library مجموعه ای از کتابخانه‌های برنامه‌نویسی پردازش تصویر و یادگیری ماشین است. این مجموعه بیشتر بر پردازش تصویر بی درنگ تمرکز دارد. در ابتدا توسط اینتل ساخته و پشتیبانی می‌شد و هم‌اکنون توسط Willow Garage و Itseez پشتیبانی می‌گردد.

ویکی پدیا ویدیوی این مطلب:

لینک یوتوب آموزش نوشتن متن فارسی روی عکس در پایتون - همه مواردی که باید بدونید

نوشتن متن در openCV

قبل از اینکه مستقیم بریم وارد مشکل بشیم اول نحوه اضافه کردن یک متن انگلیسی رو به تصویر بریم و بررسی کنیم:

 

python
import cv2
file_name = 'cv-spring-2021.png'
img = cv2.imread(file_name)

# font 

font = cv2.FONT_HERSHEY_SIMPLEX 

# org 
org = (50, 50) 

# fontScale 
fontScale = 1

# Blue color in BGR 
color = (255, 0, 0) 

# Line thickness of 2 px 
thickness = 2

image = cv2.putText(img, 'Hi There', org, font, 
fontScale, color, thickness, cv2.LINE_AA)

cv2.imshow('image',image)
cv2.waitKey(0) # get time if set 0 then wait until press key
cv2.destroyAllWindows()

با استفاده از این تیکه کد میتونیم Hi There رو به تصویرمون اضافه میکنیم مثل اینجا میشه خروجی:

اضافه کردن متن انگلیسی در opencv

حالا بیاییم و متن رو تبدیل کنیم به «سلام» یعنی فقط یک خط رو ادیت کنیم نسبت به کد قبلی

image = cv2.putText(img, ‘سلام’, org, font, fontScale, color, thickness, cv2.LINE_AA)

حالا انتظار داریم که چاپ بشه به سادگی ولی نتیجه …

مشکل فارسی نویسی در opencv

حالا مشکل از کجاست؟

متاسفانه برای من هم قابل باور نیستش ولی به نظر مشکل از اینه هستش:

python
cv2.putText

لینک stackoverflow

حالا یک چیز مهم تر ASCII چیه؟ no-ascii چیه؟ UTF-8 چیه؟

ASCII code

واقعیتش اینجا نمیخوام براتون تمام مواردش رو بگم, به صورت خلاصه در گذشته با توجه به اینکه حافظه کامپیوتر ها محدود بودش و در ابتدا زبان انگلیسی تنها زبان استفاده کنندگان بودش کمتیه ای تصمیم گرفت که ۷ بیت که میتونه ۱۲۸ حالت رو تشکیل بده برای هر کارکتر در نظر بگیره.

یعنی کارکتر های اصلی کامپیوتر + الفبای انگلیسی کوچیک + الفبای انگلیسی بزرگ  شدن شامل این مورد.

 

یکم عجیب باشه که باید بگم این استاندارد برمیگرده به ۱۹۶۰ میلادی ولی حالا و اینجا چرا این استاندارد برای ما مشکل ایجاد میکنه؟ خب با گذشت زمان و نبودن همچین مشکل حافظه ای و از طرفی پیشرفت کامپیوتر ها باعث شد که استفاده کنندگان با زبان های مختلفی اضافه بشن که ۱۲۸ حالت جوابگوی اونها نبودش.

UTF-8 به چه کارمون میادش؟

utf-8-persian-character

UTF-8 یکی از روش های کدگذاری که وجود داره UTF-8 است که در این روش ما 1,112,064 کارکتر یکتا میتونیم داشته باشیم که ۱۲۸ تای اول اون شبیه ASCII هست.

عدد 1,112,064 به اندازه ای هستش که بتونیم همه زبان های اصلی رو پوشش بدیم و همین الان شما دارید این صفحه رو با استاندارد UTF-8 میبنید و هر صفحه فارسی دیگری رو میرید, حالا بریم به بخش راه حل.

 

 

راه حل فارسی نویسی در OpenCV

در حال حاضر من این روش رو میدونم که ممکنه بهترین روش ممکنه نباشه ولی کاراست, اگر روش دیگری میشناسید حتما توی بخش کامنت ها بنویسید.

راه حل من به صورت خلاصه این هستش که بیاییم از PIL (کتابخونه پایتونی) استفاده کنیم برای این کار چون مستقیما هیچ راهی نیستش برای این کار (متاسفانه!)

اگر که این کتابخونه رو ندارید با استفاده از

pip install Pillow

نصب کنید

حالا اولین قدم بریم کدمون رو بررسی کنیم:

 

python
from PIL import Image, ImageFont, ImageDraw 
file_name = 'cv-spring-2021.png'
image = Image.open(file_name) 
font = ImageFont.truetype('vazir.ttf', 40, encoding='unic')
draw = ImageDraw.Draw(image) 
text = 'سلام من امین هستم و این یک متن فارسیت.'
draw.text((50, 100), text,(255,2,2), font = font) 
image.show()

خب همه چیز به نظر اوکی هستش حتی فونت وزیر هم فراخوانی کردیم و تموم شد و رفت پس بریم نتیجه رو ببینیم.

دریافت فونت وزیر

نتیجه:

مشکل فراخوانی فارسی در PIL

یک فرقی کرده درسته؟ قبلا نمیدونستیم چی چی رو داره چاپ میکنه الان دو مشکل داره

۱. از چپ به راست هست

۲. حروف الفبا از هم جدا هستن

مثلا سلام شده «م‌ا‌ل‌س»

اگر میخواستیم چینی بنویسیم مشکلمون اینجا تموم میشدش مثلا “端午节就要到了”

نوشتن کارکتر چینی در PIL

چون چینی از چپ به راست هستش و فاصله بین حروفش هم مشکلی نیستش, خب بریم این مشکل رو حل کنیم که متن تر و تمیز فارسی داشته باشیم.

 

فارسی و راست چین نویسی روی تصاویر پایتون

ابتدا باید دو کتابخونه رو نصب کنیم

  1. arabic_reshaper
  2. python-bidi

با استفاده از pip

bash
pip install --upgrade arabic-reshaper

pip install python-bidi

حالا بریم رویه رو ببینیم

 

python
import arabic_reshaper
from bidi.algorithm import get_display

from PIL import Image, ImageFont, ImageDraw 
file_name = 'cv-spring-2021.png'
image = Image.open(file_name) 
font = ImageFont.truetype('vazir.ttf', 40, encoding='unic')
draw = ImageDraw.Draw(image) 
text = 'سلام من امین هستم و این یک متن فارسیت.'
reshaped_text = arabic_reshaper.reshape(text) # correct its shape
bidi_text = get_display(reshaped_text) # correct its direction

draw.text((50, 100), bidi_text,(255,2,2), font = font) 
image.show()

نسبت به قبل دو خط کد جدا از فراخوانی کتابخونه ها اضافه کردم و یک متغییر رو تغییر دادم

اول نتیجه رو ببینیم که این همه منتظر بودیم:

فارسی نویسی با حفظ راست چین بودن و فاصله در پایتون

ابتدا خط

python
reshaped_text \= arabic_reshaper.reshape(text)

این خط از حالت فعلی تبدیل میکند به حالت مناسب که از لحاظ دیداری فرق زیادی ندارد

‘ﺳﻼﻡ ﻣﻦ ﺍﻣﯿﻦ ﻫﺴﺘﻢ ﻭ ﺍﯾﻦ ﯾﮏ ﻣﺘﻦ ﻓﺎﺭﺳﯿﺖ.’

این خروجی متغییر reshaped_text میباشد حالا در خط بعدی

python
bidi_text \= get_display(reshaped_text)

تبدیل میکنیم به حالتی که نیم فاصله ها رو درست نشون بده که اگر متغیر bidi_text رو چاپ کنیم این رو برامون نشون میده:

‘.ﺖﯿﺳﺭﺎﻓ ﻦﺘﻣ ﮏﯾ ﻦﯾﺍ ﻭ ﻢﺘﺴﻫ ﻦﯿﻣﺍ ﻦﻣ ﻡﻼﺳ’

و این رو میدیم به تابع draw.text تا برای ما بکشدش

حالا قدم بعد تر اگر بخواهیم از تصویر مذکور توی opencv استفاده کنیم میتونیم اون رو به این طریق بفرستیم به opencv

ابتدا نیاز به ماژول cv2 و numpy دارید

python
open_cv_image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
cv2.imshow('open_cv_image',open_cv_image)
cv2.waitKey(0) # get time if set 0 then wait until press key
cv2.destroyAllWindows()

اینم هم نتیجه نهایی توی یک پنجره OpenCV

خروجی نهایی فارسی نویسی در تصاویر توی OpenCV و PIL

منابع:

How to draw Chinese text on the image using `cv2.putText`correctly? (Python+OpenCV)

Python PIL | ImageFont.truetype()

آشنایی با کدهای اسکی (ASCII) — به زبان ساده How to write RTL(Arabic/Persian) text on images in python.

Convert image from PIL to openCV format