Opencv true type font reversing and splitting arabic characters

  arabic, c++, opencv, python, truetype

Arabic letters are written cursively and read from right to left. I’m trying to render the word مستقبل which means future and reads from right to left (begins with م and ends with ل) using opencv’s FreeType2, and a ttf. Following the documentation example, I do:

#include <opencv2/opencv.hpp>
#include <opencv2/freetype.hpp>


void render_text(const cv::String& text, const cv::String& font){
    int font_height = 60;
    int thickness = -1;
    int line_style = 4;
    int baseline=0;
    cv::Ptr<cv::freetype::FreeType2> ft2;
    ft2 = cv::freetype::createFreeType2();
    ft2->loadFontData(font, 0 );
    cv::Size text_size = ft2->getTextSize(text,
                                     font_height,
                                     thickness,
                                     &baseline);
    cv::Mat img(500, 500, CV_8UC3, cv::Scalar::all(0));
    if(thickness > 0){
        baseline += thickness;
    }
    cv::Point origin((img.cols - text_size.width) / 2,
                  (img.rows + text_size.height) / 2);
    ft2->putText(img, text, origin, font_height,
                 cv::Scalar::all(255), thickness, line_style, true );
    cv::imshow("default", img);
    cv::waitKey(0);
    cv::destroyAllWindows();
}


int main() {
    render_text("مستقبل", "Cairo/Cairo-Regular.ttf");
    return 0;
}

Which results in (incorrect):

reversed

I was able to render the word using the same font in the proper order using PIL

import numpy as np
from cv2 import cv2
from PIL import Image, ImageDraw, ImageFont


def render_text(text, font, font_size=60):
    font = ImageFont.truetype(font, font_size)
    image = Image.new('RGB', font.getsize(text), (0, 0, 0))
    draw = ImageDraw.Draw(image)
    draw.text((0, 0), text, (255, 255, 255), font=font)
    cv2.imshow('default', np.array(image))
    cv2.waitKey(0)
    cv2.destroyAllWindows()


if __name__ == '__main__':
    render_text('مستقبل', 'Cairo/Cairo-Regular.ttf')

which results in (correct):

correct

But it’s slow, which led me to the attempt shown earlier with opencv after failing to find the freetype2 in opencv-python. How to get it to render words in the correct order? preferably in python but c++ is fine. Other opencv alternatives are welcome as long as they:

  • Are faster than PIL
  • Render in the proper order.
  • Don’t split letters

Source: Windows Questions C++

LEAVE A COMMENT