2

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 or opencv-contrib-python. How to get it to render words in the correct order in python or c++? Other opencv alternatives are welcome as long as they:

  • Are faster than PIL
  • Render in the proper order.
  • Don't split letters
watch-this
  • 1
  • 4
  • 20
  • Try pango to render on a cairo surface, then convert that to opencv mat like e.g. here https://stackoverflow.com/questions/19948319/how-to-convert-cairo-image-surface-to-opencv-mat-in-c – n. m. could be an AI Nov 02 '21 at 06:06

1 Answers1

0

That's a known problem with the freetype module in opencv_contrib.

It has not been reported as an issue yet (as far as I can see) because freetype text rendering will graduate from being a contrib module to being part of OpenCV proper... in OpenCV 5.

That being in contrib currently is also the reason it's not available to you from the opencv-python package. You need the opencv-contrib-python package... that might include it.

Hopefully the reimplementation will fix this. I don't know when OpenCV 5 will be released. It is currently under active development.

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
  • It's unavailable in `opencv-contrib-python` and I still get `Error 'module' object has no attribute 'freetype'`. So, any opencv alternatives or workarounds? – watch-this Nov 02 '21 at 12:21