Basically 3 steps
import re
import cv2
import math
import pytesseract
import numpy as np
import pandas as pd
from deep_translator import GoogleTranslator
from PIL import Image, ImageDraw, ImageOps, ImageFont
import matplotlib.pyplot as plt
%matplotlib inline
def show_image(img, size=6):
"""
For display single image
"""
plt.figure(figsize = (size, size))
plt.axis('off')
plt.imshow(img)
def show_images(images, titles=None, size=4, spacing=0.03):
"""
For display multiple image in horizontal
"""
num_images = len(images)
if titles == None:
titles = [f'image {i+1}' for i in range(num_images)]
fig = plt.figure(figsize=(size * num_images, size*2))
fig.patch.set_facecolor('gainsboro')
for i, (image, var_name) in enumerate(zip(images, titles)):
ax = fig.add_subplot(1, num_images, i + 1)
ax.imshow(image, cmap="gray")
ax.axis('off')
ax.set_title(var_name)
ax.xaxis.set_ticks([])
ax.yaxis.set_ticks([])
ax.set_aspect('equal')
fig.subplots_adjust(wspace=spacing)
plt.show()
Read the image with cv2.
Make it grayscale and then black and white to increase the accuracy of text recognition
img_file = 'sapiens.jpg'
cv_image = cv2.imread(img_file)
rgb_img = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
gray_img = cv2.cvtColor(cv_image, cv2.COLOR_RGB2GRAY)
def binarize_image(cv_image):
gray_img = cv2.cvtColor(cv_image, cv2.COLOR_RGB2GRAY)
bw_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
return bw_img
bw_img = binarize_image(cv_image)
Show them.
titles = ['RGB','GRAY','BW']
images = [rgb_img, gray_img, bw_img]
show_images(images, titles)
def detect_text(image, oem=3, psm=6, lang='eng'):
config = f'-l {lang} --oem {oem} --psm {psm}'
text = pytesseract.image_to_string(image, config = config)
return ''.join(text)
texts = [detect_text(image) for image in images]
texts
['Yuval Noah\nFarari\n*\n\nS apiens\nA Brief\nHistory of\nHumankind\n', 'Yuval Noah\nHarari\nS apiens\nA Brief\nHistory of\nHumankind\n', 'Yuval Noah\nHarari\nS apiens\nA Brief\nHistory of\nHumankind\n']
Acquires coordinate data as well as text information.
Make it return as a data frame by default.
def detect_data(image, oem=3, psm=6, lang='eng', types='df'):
config = f'-l {lang} --oem {oem} --psm {psm}'
if types == 'df':
types = 'data.frame'
elif types == 'dict':
types = pytesseract.Output.DICT
data = pytesseract.image_to_data(image, config = config, output_type = types )
return data
%%time
data = detect_data(bw_img)
data.head()
CPU times: user 131 ms, sys: 19 ms, total: 150 ms Wall time: 624 ms
| level | page_num | block_num | par_num | line_num | word_num | left | top | width | height | conf | text | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1683 | 2560 | -1.000000 | NaN |
| 1 | 2 | 1 | 1 | 0 | 0 | 0 | 124 | 165 | 1431 | 2234 | -1.000000 | NaN |
| 2 | 3 | 1 | 1 | 1 | 0 | 0 | 124 | 165 | 1433 | 2216 | -1.000000 | NaN |
| 3 | 4 | 1 | 1 | 1 | 1 | 0 | 295 | 165 | 1088 | 159 | -1.000000 | NaN |
| 4 | 5 | 1 | 1 | 1 | 1 | 1 | 295 | 165 | 512 | 159 | 96.453064 | Yuval |
Create a data frame and process the data.
def get_datas(data):
df = pd.DataFrame(data).dropna()
df = df[df.text.str.strip() != '']
df['x2'] = df.width + df.left
df['y2'] = df.height + df.top
group_df = df.groupby(['block_num','par_num','line_num']).agg({
'text': ' '.join,
'left': 'min',
'top': 'min',
'width': 'max',
'height': 'max',
'x2': 'max',
'y2': 'max'
}).reset_index()
text_list = '\n'.join(group_df.text.tolist())
coordinate = group_df.iloc[:,4:].values.tolist()
return text_list, coordinate
text_list, coordinate = get_datas(data)
text_list, coordinate
('Yuval Noah\nHarari\nS apiens\nA Brief\nHistory of\nHumankind',
[[295, 165, 512, 159, 1383, 324],
[539, 430, 605, 142, 1144, 572],
[124, 956, 1179, 329, 1534, 1371],
[410, 1499, 588, 198, 1267, 1697],
[223, 1839, 896, 248, 1462, 2106],
[128, 2176, 1427, 223, 1555, 2399]])
It use google translate here.
If we translate each word detected by OCR individually, the meaning will be unclear, and calling it each time will take time, so we will process it as a string at once.
However, Google Translate has a limit of 5000 characters or less.
Therefore, define a function to split the text if it is over 5000 characters.
First, separate by 5000.
Determine the index of a newline by searching backwards for the nearest newline.
Split the original text at specified index and return.
def split_text(text, max_length=5000):
if len(text) <= max_length:
return [text]
pre = text[:max_length]
for i in range(len(pre)):
if pre[::-1][i] == '\n':
num = pre[::-1].index('\n')
break
part_one = text[:max_length-num]
part_two = text[max_length-num:]
return [part_one, part_two]
def translate_text(text, target, source='auto'):
batch = split_text(text)
translated_text = GoogleTranslator(source, target).translate_batch(batch)
return ''.join(translated_text).split('\n')
lang = 'fr'
text_fr = translate_text(text_list, lang)
print(text_fr)
['Yuval Noé', 'Harari', 'Sapiens', 'Une brève', "L'histoire de", 'Humanité']
draw_image = rgb_img.copy()
fontCV = cv2.FONT_HERSHEY_DUPLEX
font_thickness = 10
for i in range(len(text_fr)):
x,y,w,h,x2,y2 = coordinate[i]
cv2.rectangle(draw_image, [x, y, x2-x, y2-y], (0,255,0), 5)
show_image(draw_image)
The green frame was created from the coordinates combined for each text line.
Fill Green frame with the background color and draw the text over it.
Crop the image at the coordinates of the text frame.
def get_colors(cv_image, val=100):
image = scale_image(cv_image, val)
flat_image = image.reshape(-1, 3)
colors, counts = np.unique(flat_image, axis=0, return_counts=True)
most_common = colors[np.argmax(counts)].tolist()
sorted_indices = np.argsort(-counts)
second_common = colors[sorted_indices[1]].tolist()
return most_common, second_common
If the image is larger in height or width than the specified size, it will be reduced to the specified size and returned.
Calculation time can be reduced.
def scale_image(cv_image, val):
if len(cv_image.shape) == 3:
height, width, _ = cv_image.shape
else: height, width = cv_image.shape
if height > val or width > val:
scale = val / max(width, height)
cv_image = cv2.resize(cv_image, None, None, scale, scale)
return cv_image
def get_optimal_font_scale(text, width):
for scale in range(1, 200)[::-1]:
textSize = cv2.getTextSize(text, fontFace=cv2.FONT_HERSHEY_DUPLEX, fontScale=scale/10, thickness=1)
new_width = textSize[0][0]
if new_width <= width:
return scale/10
return 1
get_colorsdraw_image = rgb_img.copy()
font_thickness = 10
for i in range(len(text_fr)):
tx = text_fr[i]
x,y,w,h,x2,y2 = coordinate[i]
bg_col, text_col = get_colors(draw_image[y:y2, x:x2], 80)
cv2.rectangle(draw_image, (x, y, x2-x, y2-y), bg_col, -1)
scale = get_optimal_font_scale(tx, x2-x)
cv2.putText(draw_image, tx, (x, y+h), fontCV, scale, text_col, font_thickness, lineType=cv2.LINE_AA)
titles = ['Original','Translated']
show_images([rgb_img, draw_image], titles)
CV2 cannot draw anything other than ASCII characters as é, è, it will became ??
Add a margin that hide extends the right edge of the title.
Adjust the font size so that the text fits as large as possible in the text box.
Pass the width and height of the box, and the font name so that it can be calculated even if the font changes.
def get_text_infos(text, width, height, font_name):
min_font_size = 10
max_font_size = 500
epsilon = 1
while min_font_size < max_font_size - epsilon:
font_size = (min_font_size + max_font_size) // 2
image = Image.new("RGB", (1, 1))
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(font_name, font_size)
box = draw.textbbox((0,0),text, font=font)
descent = font.font.descent
_, (_, offset_y) = font.font.getsize(text)
if box[2] <= width and box[3] <= height+offset_y:
min_font_size = font_size
else:
max_font_size = font_size
return min_font_size, box
def text_to_image(cv_image, text_list, box_list, font_name):
rgb_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
pil_image = Image.fromarray(rgb_image)
draw = ImageDraw.Draw(pil_image)
for i in range(len(text_list)):
text = text_list[i]
x, y, w, h, x2, y2 = box_list[i]
bg_col, tex_col = get_colors(rgb_image[y:y2, x:x2], 80)
margin = np.ceil(min(h, w) *0.1//2)
draw.rectangle([x-margin, y-margin, x2+margin, y2+margin], fill=tuple(bg_col))
size, bbox = get_text_infos(text, x2-x, y2-y, font_name)
x_center = (x2+x - bbox[2]) // 2
font = ImageFont.truetype(font_name, size)
draw.text((x_center, y), text, fill=tuple(tex_col), font=font, anchor="lt")
return pil_image
Define a font and pass it to the function for output.
font_fr = 'NewYork.ttf'
font_fr_sans = 'Arial.ttf'
image_fr = text_to_image(cv_image, text_fr, coordinate, font_fr)
show_images([rgb_img, image_fr])
Pretty nice Image.
Next, Create other Languages.
lang = 'ja'
text_ja = translate_text(text_list, lang)
font_ja ='/System/Library/Fonts/ヒラギノ明朝 ProN.ttc'
font_ja_sans = 'ヒラギノ角ゴシック W6.ttc'
image_ja = text_to_image(cv_image, text_ja, coordinate, font_ja)
lang = 'th'
text_th = translate_text(text_list, lang)
font_th = "/Library/Fonts/Chonburi-Regular.ttf"
font_th_sans = '/Library/Fonts/NotoSansThai-SemiBold.ttf'
image_th = text_to_image(cv_image, text_th, coordinate, font_th)
lang = 'ru'
text_ru = translate_text(text_list, lang)
font_ru = '/System/Library/Fonts/Supplemental/Baskerville.ttc'
font_ru_sans = '/System/Library/Fonts/Menlo.ttc'
image_ru = text_to_image(cv_image, text_ru, coordinate, font_ru)
multi_languages = ['Original','French','Japanese','Thai','Russian']
translated_images = [rgb_img, image_fr, image_ja, image_th, image_ru]
show_images(translated_images, multi_languages)
img_file = 'the_gene.png'
cv_image = cv2.imread(img_file)
rgb_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
bw_img = binarize_image(cv_image)
data = detect_data(bw_img, 3, 1)
text_list, coordinate = get_datas(data)
text_list
'THE\nGENE\nAN INTIMATE HISTORY\nSIDDHARTHA\nMUKHERJEE\nPULITZER PRIZE~WINNING AUTHOR OF\nTHE EMPEROR OF ALL MALADIES'
If the text looks weird, try adjusting the parameters.
text_fr = translate_text(text_list, 'fr')
image_fr = text_to_image(cv_image, text_fr, coordinate, font_fr_sans)
text_ja = translate_text(text_list, 'ja')
image_ja = text_to_image(cv_image, text_ja, coordinate, font_ja_sans)
text_th = translate_text(text_list, 'th')
image_th = text_to_image(cv_image, text_th, coordinate, font_th_sans)
text_ru = translate_text(text_list, 'ru')
image_ru = text_to_image(cv_image, text_ru, coordinate, font_ru_sans)
show_images([rgb_image, image_fr, image_ja, image_th, image_ru], multi_languages)
The text color and background color were reversed.
Plot and check the colors used.
from matplotlib.colors import ListedColormap
import seaborn as sns
sns.set()
def plot_color_freq(cv_image, coordinate):
x, y, w, h, x2, y2 = coordinate
crop_box = rgb_image[y:y2, x:x2]
scaled_image = scale_image(crop_box, 100)
flat_image = scaled_image.reshape(-1, 3)
show_images([crop_box, scaled_image],['Original Text Area','Scaled Text Area'])
colors, counts = np.unique(flat_image, axis=0, return_counts=True)
sorted_indices = np.argsort(-counts)
top_colors = colors[sorted_indices][:40]
top_counts = counts[sorted_indices][:40]
cmap = ListedColormap(top_colors / 255.0)
fig, ax = plt.subplots(figsize=(18, 6))
for i, zips in enumerate(zip(top_colors, top_counts)):
color, count = zips
rgb_string = "({},{},{})".format(*color)
plt.bar(rgb_string, count, color=cmap.colors[i], edgecolor = "None")
plt.annotate(count , xy=(i, count+10),
ha="center", va="center", color='gray', fontsize=12)
plt.title("Color Frequency in the Image", fontsize=14)
plt.xlabel("Color")
plt.ylabel("Frequency")
fig.autofmt_xdate(rotation=45)
plt.show()
plot_color_freq(cv_image, coordinate[1])
The reason why we determined that black is the most common color is that the original background color, which is whitish, is not a single color, but multiple.
For example, there are multiple approximations such as (244, 246, 235) but also (243, 235, 234).
Create a function that collects approximate color values and obtains the color.
Use k-means clustering for color quantization, we will get two colors from text box.
Reference documentation (https://docs.opencv.org/3.4/d1/d5c/tutorial_py_kmeans_opencv.html)
It takes images that contain text and clusters them. If set k=2 can't get the colors right, so set k=4 and more.
Determine the color that is the most_common and the color that is the second_common.
However, first get most frequency, most_common as background color.
Then find the text color that has the largest gap with the background color.
def color_quantization(crop_box):
sharped_image = sharpen_image(crop_box)
scaled_image = scale_image(sharped_image, 200)
flat_image = scaled_image.reshape(-1, 3)
flat_image = np.float32(flat_image)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
k = 4
ret, label, center = cv2.kmeans(flat_image, k, None, criteria, 10, cv2.KMEANS_PP_CENTERS)
colors = center.astype(np.uint8)
segmented_image = colors[label.flatten()].reshape(scaled_image.shape)
flat_image = segmented_image.reshape(-1, 3)
colors, counts = np.unique(flat_image, axis=0, return_counts=True)
most_common = colors[np.argmax(counts)].tolist()
sorted_indices = np.argsort(-counts)
color_diff = np.linalg.norm(colors - most_common, axis=1)
max_diff_index = np.argmax(color_diff)
second_common = colors[max_diff_index].tolist()
return most_common, second_common
Sharpens the image and returns it.
This prevents colors from becoming particularly blurry, especially for small images.
def sharpen_image(cv_image):
gaussian_image = cv2.GaussianBlur(cv_image, (0, 0), 3)
sharpen_image = cv2.addWeighted(cv_image, 1.2, gaussian_image, -0.2, 0)
return sharpen_image
def text2image(cv_image, text_list, box_list, font_name):
rgb_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
pil_image = Image.fromarray(rgb_image)
draw = ImageDraw.Draw(pil_image)
for i in range(len(text_list)):
text = text_list[i]
x, y, w, h, x2, y2 = box_list[i]
bg_col, tex_col = color_quantization(rgb_image[y:y2, x:x2])
margin = min(np.ceil(h*0.1//2), np.ceil(w*0.1//2))
draw.rectangle([x-margin, y-margin, x2+margin, y2+margin], fill=tuple(bg_col))
size, bbox = get_text_infos(text, x2-x, y2-y, font_name)
x_center = (x2+x - bbox[2]) // 2
font = ImageFont.truetype(font_name, size)
draw.text((x_center, y), text, fill=tuple(tex_col), font=font, anchor="lt")
return pil_image
image2fr = text2image(cv_image, text_fr, coordinate, font_fr_sans)
image2ja = text2image(cv_image, text_ja, coordinate, font_ja_sans)
image2th = text2image(cv_image, text_th, coordinate, font_th_sans)
image2ru = text2image(cv_image, text_ru, coordinate, font_ru_sans)
show_images([rgb_image,image2fr, image2ja, image2th, image2ru],multi_languages)
Now, layout is close to the original.
Another one.
Since the original is in French, specify fra as the language to retrieve the data.
img_file = 'lecapital.jpg'
cv_image = cv2.imread(img_file)
rgb_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
bw_img = binarize_image(cv_image)
data = detect_data(bw_img, 3, 6, 'fra')
text_list, coordinate = get_datas(data)
text_list
"mbaudiolo\nTHOMAS\nPIKETTY\nLE CAPITAL\nau xx siècle\nUN SUCCÈS PLANÉTAIRE\n2,5 MILLIONS D'EXEMPLAIRES VENDUS\nDANS LE MONDE"
text_en = translate_text(text_list, 'en')
text_ja = translate_text(text_list, 'ja')
text_th = translate_text(text_list, 'th')
text_ru = translate_text(text_list, 'ru')
font_en = font_fr
font_en_sans = font_fr_sans
image_en = text2image(cv_image, text_en, coordinate, font_en_sans)
image_ja = text2image(cv_image, text_ja, coordinate, font_ja_sans)
image_th = text2image(cv_image, text_th, coordinate, font_th_sans)
image_ru = text2image(cv_image, text_ru, coordinate, font_ru_sans)
title = ['Original','English','Japanese','Thai','Russia']
images = [rgb_image,image_en, image_ja, image_th, image_ru]
show_images(images, title)
img_file = "The_Holstee_Manifesto.png"
cv_image = cv2.imread(img_file)
rgb_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
bw_img = binarize_image(cv_image)
data = detect_data(bw_img, 1, 11, 'eng')
text_list, coordinate = get_datas(data)
text_list
"THIS IS YOUR\nDO WHAT YOU LOVE,\nAND DO IT OFTEN.\nLIFE,\nIF YOU DON'T LIKE SOMETHING, CHANGE IT.\nIF YOU DON’ T LIKE YOUR JOB, QUIT.\nIF YOU DON'T HAVE ENOUGH TIME, STOP WATCHING TV.\nIF YOU ARE LOOKING FOR THE LOVE OF YOUR LIFE, STOP\nTHEY WILL BE WAITING FOR YOU WHEN YOU\nSTART DOING THINGS YOU LOVE\nSTOP OVER ANALYZING, ALL EMOTIONS ARE BEAUTIFUL.\nWHEN YOU EAT, APPRECIATE\nLIFE IS SIMPLE. every LAst BITE\nOPEN YOUR MIND, ARMS, AND HEART TO NEW THINGS\nAND PEOPLE, WE ARE UNITED IN OUR DIFFERENCES\nASK THE NEXT PERSON YOU SEE WHAT THEIR PASSION I5\nAND SHARE YOUR INSPIRING DREAM WITH THEM.\nSOME OPPORTUNITIES ONLY COME ONCE, SEIZE THEM\nTRAVEL OFTEN? tirce vou rino vourseir\nLIFE IS ABOUT THE PEOPLE YOU MEET, AND\nTHE THINGS YOU CREATE WITH THEM\nSO GO OUT AND START CREATING\nLIFE IS\nLIVE YOUR DREAM\nAND SHARE\nSHORT.\nYOUR PASSION\nTHE HOLSTEE MANIFESTO © 2009 HOLSTEE.COM DESIGN BY RACHAEL BERESH\nte Bre"
text_fr = translate_text(text_list, 'fr')
text_ja = translate_text(text_list, 'ja')
text_th = translate_text(text_list, 'th')
text_ru = translate_text(text_list, 'ru')
font_fr_al = '/Library/Fonts/AlexandriaFLF-Bold.ttf'
image_fr = text2image(cv_image, text_fr, coordinate, font_fr_al)
image_ja = text2image(cv_image, text_ja, coordinate, font_ja_sans)
image_th = text2image(cv_image, text_th, coordinate, font_th)
image_ru = text2image(cv_image, text_ru, coordinate, font_ru_sans)
title = ['Original','French','Japanese','Thai','Russia']
images = [rgb_image, image_fr, image_ja, image_th, image_ru]
show_images(images, title, 6)
This is Holstee's famous manifesto.
Some text was obscured by lines with mixed case letters.
By adjusting the parameters when recognizing text with OCR, it is possible to recognize even two columns.
Let's display a sample below.
img_file = 'apple.png'
cv_image = cv2.imread(img_file)
rgb_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
bw_img = binarize_image(cv_image)
data = detect_data(bw_img, 3, 1)
text_list, coordinate = get_datas(data)
text_list
'Which iPhone\nis right for you?\nNew\niPhone 15 Pro\nThe ultimate iPhone.\nFrom $999\nLearn more >\n6.7" or 6.1"\nSuper Retina XDR\ndisplay?\nProMation technology\nAlways-On display\nTitanium with textured\nmatte glass back\nAction button\nNew\niPhone 15\nA total powerhouse.\nFrom $799°\nLearn more >\n6.7" or 6.\nSuper Retina XDR\ndisplay*\nAluminum with color-infused\nglass back\nRing/Silent switch'
text_fr = translate_text(text_list, 'fr')
text_ja = translate_text(text_list, 'ja')
text_th = translate_text(text_list, 'th')
text_ru = translate_text(text_list, 'ru')
image_fr = text2image(cv_image, text_fr, coordinate, font_fr_sans)
image_ja = text2image(cv_image, text_ja, coordinate, font_ja_sans)
image_th = text2image(cv_image, text_th, coordinate, font_th_sans)
image_ru = text2image(cv_image, text_ru, coordinate, font_ru_sans)
title = ['Original','French','Japanese','Thai','Russia']
images = [rgb_image, image_fr, image_ja, image_th, image_ru]
show_images(images, title, 8)
Display the text in a large size so that it can be read.
screenshot_th = Image.open('screenshot_th.png')
show_images([rgb_image, image_th, screenshot_th],
['Original','Translated to Thai','Thai Web page Screenshot'],
8)
screenshot_jp = Image.open('screenshot_jp.png')
show_images([rgb_image, image_ja, screenshot_jp],
['Original','Translated to Japanese','Japanese Web page Screenshot'],
8)
img_file = 'sample.jpg'
cv_image = cv2.imread(img_file)
rgb_img = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
bw_img = binarize_image(cv_image)
titles = ['RGB','BW']
images = [rgb_img, bw_img]
show_images(images, titles, 6)
Parameters should be adjusted for best results.
data = detect_data(bw_img, 3, 11)
text_list, coordinate = get_datas(data)
text_list
'BALANCED FOOD\nean\nY\n(gorigM\nLOCK\nCALORIE MATE BLOCK contains a nutritionally balanced source of the\nenergy needed for daily activities. CALORIE MATE BLOCK is great for\npeople who are always on-the-go, needing an easy way of consuming\nenergy and nutrition whether it is for breakfast, work, sports, study, or\nany busy time. @¢Product:Balanced nutrition food(solid type) ¢ingredients:\nWheat flour, margarine, sugar, natural cheese, egg, almond powder,\nstarch, nonfat milk powder, soy protein, wheat protein, salt /sodium\ncaseinate, modified starch, flavors and carotenoid color. eNet weight:80g\nBest before:See bottom panel. Manufacturer: Otsuka Pharmaceutical\nCo., Ltd. 2-9 Kanda Tsukasa-machi, Chiyoda-ku, Tokyo, Japan. @Nutrition\ninformation per serving(80g):Energy 400kcal, protein 8.4g, fat 22.2g,\ncarbohydrate 42.7g(sugar 40.7g, dietary fiber 2g), salt equivalent 0.94g,\ncalcium 200mg, iron 2.0mg, magnesium 50mg, phosphorus 100mg, vi-\ntaminA 385yg, vitaminB: 0.6mg, vitaminBz 0.7mg, vitaminBe 0.65mg,\nvitaminB.2 1.2, niacin 6.5mg, pantothenic acid 2.4mg, folic acid 120g,\nvitaminC 50mg, vitaminD 2.8yg and vitaminE 3.2mg. ¢Note:To insure\nfreshness, please eat as soon as possible after opening the package\n—.\na “\nStn'
text_fr = translate_text(text_list, 'fr')
text_ja = translate_text(text_list, 'ja')
text_th = translate_text(text_list, 'th')
text_ru = translate_text(text_list, 'ru')
image_fr = text2image(cv_image, text_fr, coordinate, font_fr_sans)
image_ja = text2image(cv_image, text_ja, coordinate, font_ja_sans)
image_th = text2image(cv_image, text_th, coordinate, font_th_sans)
image_ru = text2image(cv_image, text_ru, coordinate, font_ru_sans)
show_images([image_fr, image_ja], multi_languages[1:3], 8)
show_images([image_th,image_ru], multi_languages[3:], 8)
Results are Red text almost recognized, big text is weird.
It seems that tesseract cannot recognize when the font sizes are different.
img_file = "samplenews.jpg"
cv_image = cv2.imread(img_file)
rgb_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
bw_img = binarize_image(cv_image)
reversed_img = cv2.bitwise_not(bw_img)
data = detect_data(rgb_image, 1, 3)
text_list, coordinate = get_datas(data)
%%time
text_fr = translate_text(text_list, 'fr')
CPU times: user 63.9 ms, sys: 10.8 ms, total: 74.8 ms Wall time: 31.9 s
%%time
image_fr = text2image(cv_image, text_fr, coordinate, font_fr)
CPU times: user 10.7 s, sys: 1.49 s, total: 12.2 s Wall time: 10.5 s
Translation is almost instantaneous, but image generation seems to take time if there are a large number of drawings.
show_images([rgb_image,image_fr],None,12)