Create an image with text translated into other languages from the original image ¶

Basically 3 steps

  • Recognize text in image
  • Translate text to other language
  • Draw translated text

Import Libraries¶

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

Dsiplay Functions¶

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 Image file¶

cv2 image¶

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)

Detect Text¶

Extract only text by OCR¶

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)

Check text detection¶

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']

Detect Text Data¶

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 pandas Data Frame¶

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

Create text list and 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]])

Text Translation¶

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.

Get often color¶

Crop the image at the coordinates of the text frame.

  • The most commonly used color set to background color
  • The second commonly used color set to font color
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

Resize Image¶

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

Change text scale to adust Text length¶

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

Show Translateed Text on the Image¶

  • Copy the image for drawing.
  • Loop over the length of the data frame.
  • Draws a filled text box using the background colors from get_colors
  • Draw translated text above text box with text color
draw_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.

Convert to PIL image to Draw Non Ascii Text¶

Adjust Font size with Width and Height¶

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
  • Convert to pil_imag to draw non-ASCII characters.
  • Specify the font and draw the text and box coordinates.
  • Set the margins to 10% of the box height or width, whichever is smaller. Divide by 2 to add 5% each to the top, bottom, left and right.
  • Calculate the font size and center the drawing position.
  • Repeat a number of text in a loop.
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.

Create Japanese¶

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)

Create Thai¶

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)

Create Russian¶

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)

Display Images¶

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)

Try Other Image¶

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.

Plot color frequency¶

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.

Color Quantization¶

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)

Photo Images¶

Read photo image as cv2 image.

Make gray image and b/w image.

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)

Text recognize test¶

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'

Create data frame to easy to see.¶

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)